internal static CmsPeriod sutCoupon()
        {
            FixedIborSwapConvention conv = INDEX.Template.Convention;
            ResolvedSwap            swap = conv.toTrade(FIXING, START, END, BuySell.BUY, 1d, 0.01).Product.resolve(REF_DATA);

            return(CmsPeriod.builder().currency(GBP).notional(NOTIONAL).startDate(START).endDate(END).unadjustedStartDate(START_UNADJUSTED).unadjustedEndDate(END_UNADJUSTED).yearFraction(YEAR_FRACTION).paymentDate(PAYMENT).fixingDate(FIXING).dayCount(ACT_360).index(INDEX).underlyingSwap(swap).build());
        }
        internal static CmsPeriod sut2()
        {
            FixedIborSwapConvention conv = INDEX.Template.Convention;
            ResolvedSwap            swap = conv.toTrade(FIXING.plusDays(1), START.plusDays(1), END.plusDays(1), BuySell.BUY, 1d, 1d).Product.resolve(REF_DATA);

            return(CmsPeriod.builder().currency(EUR).notional(NOTIONAL + 1).startDate(START.plusDays(1)).endDate(END.plusDays(1)).unadjustedStartDate(START_UNADJUSTED.plusDays(1)).unadjustedEndDate(END_UNADJUSTED.plusDays(1)).yearFraction(YEAR_FRACTION + 0.01).paymentDate(PAYMENT.plusDays(1)).fixingDate(FIXING.plusDays(1)).floorlet(STRIKE).dayCount(ACT_365F).index(SwapIndices.EUR_EURIBOR_1100_5Y).underlyingSwap(swap).build());
        }
Beispiel #3
0
        /// <summary>
        /// Computes the adjustment to the forward rate for a CMS coupon.
        /// <para>
        /// The adjustment to the forward rate, is the quantity that need to be added to the forward rate to obtain the
        /// adjusted forward rate. The adjusted forward rate is the number which used in the same formula used for
        /// Ibor coupon pricing (forward * notional * accrual factor * discount factor) will provide the correct present value.
        /// </para>
        /// <para>
        /// For cap or floor the result is the adjustment to the forward rate for the coupon equivalent to the cap/floor,
        /// i.e. the coupon with the same dates and index but with no cap or floor strike.
        ///
        /// </para>
        /// </summary>
        /// <param name="cmsPeriod">  the CMS period, which should be of the type <seealso cref="CmsPeriodType#COUPON"/> </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the adjusted forward rate </returns>
        public double adjustmentToForwardRate(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            CmsPeriod coupon = cmsPeriod.toCouponEquivalent();
            double    adjustedForwardRate = this.adjustedForwardRate(coupon, provider, swaptionVolatilities);
            double    forward             = swapPricer.parRate(coupon.UnderlyingSwap, provider);

            return(adjustedForwardRate - forward);
        }
Beispiel #4
0
        public virtual void test_builder_multiCurrencyIndex()
        {
            CmsPeriod period3 = CmsPeriodTest.sut2();

            assertThrowsIllegalArg(() => ResolvedCmsLeg.builder().payReceive(RECEIVE).cmsPeriods(PERIOD_1, period3).build());
            CmsPeriod period4 = CmsPeriodTest.sutCoupon();

            assertThrowsIllegalArg(() => ResolvedCmsLeg.builder().payReceive(RECEIVE).cmsPeriods(PERIOD_1, period4).build());
        }
Beispiel #5
0
        /// <summary>
        /// Computes the adjusted forward rate for a CMS coupon.
        /// <para>
        /// The adjusted forward rate, is the number such that, multiplied by the notional, the year fraction and the payment
        /// date discount factor, it produces the present value. In other terms, it is the number which used in the same
        /// formula used for Ibor coupon pricing will provide the correct present value.
        /// </para>
        /// <para>
        /// For period already fixed, this number will be equal to the swap index fixing.
        /// </para>
        /// <para>
        /// For cap or floor the result is the adjusted forward rate for the coupon equivalent to the cap/floor,
        /// i.e. the coupon with the same dates and index but with no cap or floor strike.
        ///
        /// </para>
        /// </summary>
        /// <param name="cmsPeriod">  the CMS period, which should be of the type <seealso cref="CmsPeriodType#COUPON"/> </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the adjusted forward rate </returns>
        public double adjustedForwardRate(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            CmsPeriod coupon    = cmsPeriod.toCouponEquivalent();
            Currency  ccy       = cmsPeriod.Currency;
            double    dfPayment = provider.discountFactor(ccy, coupon.PaymentDate);
            double    pv        = presentValue(coupon, provider, swaptionVolatilities).Amount;

            return(pv / (coupon.Notional * coupon.YearFraction * dfPayment));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the present value curve sensitivity by simple forward rate estimation.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the present value sensitivity </returns>
        public virtual PointSensitivityBuilder presentValueSensitivity(CmsPeriod cmsPeriod, RatesProvider provider)
        {
            Currency  ccy           = cmsPeriod.Currency;
            LocalDate valuationDate = provider.ValuationDate;

            if (valuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(PointSensitivityBuilder.none());
            }
            LocalDate fixingDate = cmsPeriod.FixingDate;
            double    dfPayment  = provider.discountFactor(ccy, cmsPeriod.PaymentDate);

            if (!fixingDate.isAfter(valuationDate))
            {     // Using fixing
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    double payoff = 0d;
                    switch (cmsPeriod.CmsPeriodType)
                    {
                    case CAPLET:
                        payoff = Math.Max(fixedRate.Value - cmsPeriod.Strike, 0d);
                        break;

                    case FLOORLET:
                        payoff = Math.Max(cmsPeriod.Strike - fixedRate.Value, 0d);
                        break;

                    case COUPON:
                        payoff = fixedRate.Value;
                        break;

                    default:
                        throw new System.ArgumentException("unsupported CMS type");
                    }
                    return(provider.discountFactors(ccy).zeroRatePointSensitivity(cmsPeriod.PaymentDate).multipliedBy(payoff * cmsPeriod.Notional * cmsPeriod.YearFraction));
                }
                else if (fixingDate.isBefore(valuationDate))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            if (!cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON))
            {
                throw new System.ArgumentException("Unable to price cap or floor in this pricer");
            }
            // Using forward
            ResolvedSwap        swap        = cmsPeriod.UnderlyingSwap;
            ZeroRateSensitivity dfPaymentdr = provider.discountFactors(ccy).zeroRatePointSensitivity(cmsPeriod.PaymentDate);
            double forward = swapPricer.parRate(swap, provider);
            PointSensitivityBuilder forwardSensi = swapPricer.parRateSensitivity(swap, provider);

            return(forwardSensi.multipliedBy(dfPayment).combinedWith(dfPaymentdr.multipliedBy(forward)).multipliedBy(cmsPeriod.Notional * cmsPeriod.YearFraction));
        }
        /// <summary>
        /// Computes the forward rate associated to the swap underlying the CMS period.
        /// <para>
        /// Returns a value only if the period has not fixed yet. If the fixing date is on or before the valuation date,
        /// an <seealso cref="IllegalArgumentException"/> is thrown.
        ///
        /// </para>
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the forward rate </returns>
        public virtual double forwardRate(CmsPeriod cmsPeriod, RatesProvider provider)
        {
            LocalDate fixingDate    = cmsPeriod.FixingDate;
            LocalDate valuationDate = provider.ValuationDate;

            if (!fixingDate.isAfter(valuationDate))
            {     // Using fixing
                throw new System.ArgumentException("Forward rate is availaible only for valuation date after the fixing date");
            }
            ResolvedSwap swap = cmsPeriod.UnderlyingSwap;

            return(swapPricer.parRate(swap, provider));
        }
Beispiel #8
0
        public virtual void test_resolve()
        {
            CmsLeg         baseFloor     = CmsLeg.builder().floorSchedule(FLOOR).index(INDEX).notional(NOTIONAL).payReceive(PAY).paymentSchedule(SCHEDULE_EUR).build();
            ResolvedCmsLeg resolvedFloor = baseFloor.resolve(REF_DATA);
            LocalDate      end1          = LocalDate.of(2016, 10, 21);
            LocalDate      fixing1       = EUR_EURIBOR_6M.calculateFixingFromEffective(START, REF_DATA);
            LocalDate      fixing2       = EUR_EURIBOR_6M.calculateFixingFromEffective(end1, REF_DATA);
            LocalDate      fixing3       = EUR_EURIBOR_6M.calculateFixingFromEffective(END, REF_DATA);
            LocalDate      endDate       = SCHEDULE_EUR.calculatedEndDate().adjusted(REF_DATA);

            CmsPeriod period1 = CmsPeriod.builder().currency(EUR).floorlet(FLOOR.InitialValue).notional(-NOTIONAL.InitialValue).index(INDEX).startDate(START).endDate(end1).unadjustedStartDate(START).unadjustedEndDate(end1).fixingDate(fixing1).paymentDate(end1).yearFraction(EUR_EURIBOR_6M.DayCount.yearFraction(START, end1)).dayCount(EUR_EURIBOR_6M.DayCount).underlyingSwap(createUnderlyingSwap(fixing1)).build();
            CmsPeriod period2 = CmsPeriod.builder().currency(EUR).floorlet(FLOOR.Steps[0].Value.ModifyingValue).notional(-NOTIONAL.Steps[0].Value.ModifyingValue).index(INDEX).startDate(end1).endDate(endDate).unadjustedStartDate(end1).unadjustedEndDate(END).fixingDate(fixing2).paymentDate(endDate).yearFraction(EUR_EURIBOR_6M.DayCount.yearFraction(end1, endDate)).dayCount(EUR_EURIBOR_6M.DayCount).underlyingSwap(createUnderlyingSwap(fixing2)).build();

            assertEquals(resolvedFloor.Currency, EUR);
            assertEquals(resolvedFloor.StartDate, baseFloor.StartDate.adjusted(REF_DATA));
            assertEquals(resolvedFloor.EndDate, baseFloor.EndDate.adjusted(REF_DATA));
            assertEquals(resolvedFloor.Index, INDEX);
            assertEquals(resolvedFloor.PayReceive, PAY);
            assertEquals(resolvedFloor.CmsPeriods.size(), 2);
            assertEquals(resolvedFloor.CmsPeriods.get(0), period1);
            assertEquals(resolvedFloor.CmsPeriods.get(1), period2);

            CmsLeg         baseFloorEnd     = CmsLeg.builder().floorSchedule(FLOOR).fixingRelativeTo(FixingRelativeTo.PERIOD_END).index(INDEX).notional(NOTIONAL).payReceive(PAY).paymentSchedule(SCHEDULE_EUR).build();
            ResolvedCmsLeg resolvedFloorEnd = baseFloorEnd.resolve(REF_DATA);
            CmsPeriod      period1End       = CmsPeriod.builder().currency(EUR).floorlet(FLOOR.InitialValue).notional(-NOTIONAL.InitialValue).index(INDEX).startDate(START).endDate(end1).unadjustedStartDate(START).unadjustedEndDate(end1).fixingDate(fixing2).paymentDate(end1).yearFraction(EUR_EURIBOR_6M.DayCount.yearFraction(START, end1)).dayCount(EUR_EURIBOR_6M.DayCount).underlyingSwap(createUnderlyingSwap(fixing2)).build();
            CmsPeriod      period2End       = CmsPeriod.builder().currency(EUR).floorlet(FLOOR.Steps[0].Value.ModifyingValue).notional(-NOTIONAL.Steps[0].Value.ModifyingValue).index(INDEX).startDate(end1).endDate(endDate).unadjustedStartDate(end1).unadjustedEndDate(END).fixingDate(fixing3).paymentDate(endDate).yearFraction(EUR_EURIBOR_6M.DayCount.yearFraction(end1, endDate)).dayCount(EUR_EURIBOR_6M.DayCount).underlyingSwap(createUnderlyingSwap(fixing3)).build();

            assertEquals(resolvedFloorEnd.Currency, EUR);
            assertEquals(resolvedFloorEnd.StartDate, baseFloor.StartDate.adjusted(REF_DATA));
            assertEquals(resolvedFloorEnd.EndDate, baseFloor.EndDate.adjusted(REF_DATA));
            assertEquals(resolvedFloorEnd.Index, INDEX);
            assertEquals(resolvedFloorEnd.PayReceive, PAY);
            assertEquals(resolvedFloorEnd.CmsPeriods.size(), 2);
            assertEquals(resolvedFloorEnd.CmsPeriods.get(0), period1End);
            assertEquals(resolvedFloorEnd.CmsPeriods.get(1), period2End);

            CmsLeg         baseCap     = CmsLeg.builder().index(INDEX).capSchedule(CAP).notional(NOTIONAL).payReceive(PAY).paymentSchedule(SCHEDULE_EUR).paymentDateOffset(PAYMENT_OFFSET).build();
            ResolvedCmsLeg resolvedCap = baseCap.resolve(REF_DATA);
            CmsPeriod      periodCap1  = CmsPeriod.builder().currency(EUR).notional(-NOTIONAL.InitialValue).index(INDEX).caplet(CAP.InitialValue).startDate(START).endDate(end1).unadjustedStartDate(START).unadjustedEndDate(end1).fixingDate(fixing1).paymentDate(PAYMENT_OFFSET.adjust(end1, REF_DATA)).yearFraction(EUR_EURIBOR_6M.DayCount.yearFraction(START, end1)).dayCount(EUR_EURIBOR_6M.DayCount).underlyingSwap(createUnderlyingSwap(fixing1)).build();
            CmsPeriod      periodCap2  = CmsPeriod.builder().currency(EUR).notional(-NOTIONAL.Steps[0].Value.ModifyingValue).index(INDEX).caplet(CAP.InitialValue).startDate(end1).endDate(endDate).unadjustedStartDate(end1).unadjustedEndDate(END).fixingDate(fixing2).paymentDate(PAYMENT_OFFSET.adjust(endDate, REF_DATA)).yearFraction(EUR_EURIBOR_6M.DayCount.yearFraction(end1, endDate)).dayCount(EUR_EURIBOR_6M.DayCount).underlyingSwap(createUnderlyingSwap(fixing2)).build();

            assertEquals(resolvedCap.Currency, EUR);
            assertEquals(resolvedCap.StartDate, baseCap.StartDate.adjusted(REF_DATA));
            assertEquals(resolvedCap.EndDate, baseCap.EndDate.adjusted(REF_DATA));
            assertEquals(resolvedCap.Index, INDEX);
            assertEquals(resolvedCap.PayReceive, PAY);
            assertEquals(resolvedCap.CmsPeriods.size(), 2);
            assertEquals(resolvedCap.CmsPeriods.get(0), periodCap1);
            assertEquals(resolvedCap.CmsPeriods.get(1), periodCap2);
        }
        public virtual void test_toCouponEquivalent()
        {
            CmsPeriod caplet        = sutCap();
            CmsPeriod cpnEquivalent = caplet.toCouponEquivalent();

            assertEquals(cpnEquivalent.CmsPeriodType, CmsPeriodType.COUPON);
            assertEquals(caplet.Currency, cpnEquivalent.Currency);
            assertEquals(caplet.StartDate, cpnEquivalent.StartDate);
            assertEquals(caplet.EndDate, cpnEquivalent.EndDate);
            assertEquals(caplet.UnadjustedStartDate, cpnEquivalent.UnadjustedStartDate);
            assertEquals(caplet.UnadjustedEndDate, cpnEquivalent.UnadjustedEndDate);
            assertEquals(caplet.FixingDate, cpnEquivalent.FixingDate);
            assertEquals(caplet.PaymentDate, cpnEquivalent.PaymentDate);
            assertEquals(caplet.Index, cpnEquivalent.Index);
            assertEquals(caplet.Notional, cpnEquivalent.Notional);
            assertEquals(caplet.YearFraction, cpnEquivalent.YearFraction);
            assertEquals(caplet.DayCount, cpnEquivalent.DayCount);
        }
Beispiel #10
0
        /// <summary>
        /// Explains the present value of the CMS period.
        /// <para>
        /// This returns explanatory information about the calculation.
        ///
        /// </para>
        /// </summary>
        /// <param name="period">  the product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the volatilities </param>
        /// <param name="builder">  the builder to populate </param>
        public void explainPresentValue(CmsPeriod period, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities, ExplainMapBuilder builder)
        {
            string    type        = period.CmsPeriodType.ToString();
            Currency  ccy         = period.Currency;
            LocalDate paymentDate = period.PaymentDate;

            builder.put(ExplainKey.ENTRY_TYPE, "Cms" + type + "Period");
            builder.put(ExplainKey.STRIKE_VALUE, period.Strike);
            builder.put(ExplainKey.NOTIONAL, CurrencyAmount.of(ccy, period.Notional));
            builder.put(ExplainKey.PAYMENT_DATE, period.PaymentDate);
            builder.put(ExplainKey.DISCOUNT_FACTOR, ratesProvider.discountFactor(ccy, paymentDate));
            builder.put(ExplainKey.START_DATE, period.StartDate);
            builder.put(ExplainKey.END_DATE, period.EndDate);
            builder.put(ExplainKey.FIXING_DATE, period.FixingDate);
            builder.put(ExplainKey.ACCRUAL_YEAR_FRACTION, period.YearFraction);
            builder.put(ExplainKey.PRESENT_VALUE, presentValue(period, ratesProvider, swaptionVolatilities));
            builder.put(ExplainKey.FORWARD_RATE, swapPricer.parRate(period.UnderlyingSwap, ratesProvider));
            builder.put(ExplainKey.CONVEXITY_ADJUSTED_RATE, adjustedForwardRate(period, ratesProvider, swaptionVolatilities));
        }
        public virtual void test_builder_coupon()
        {
            CmsPeriod testCoupon = sutCoupon();

            assertFalse(testCoupon.Caplet.HasValue);
            assertFalse(testCoupon.Floorlet.HasValue);
            assertEquals(testCoupon.CmsPeriodType, CmsPeriodType.COUPON);
            assertEquals(testCoupon.Currency, GBP);
            assertEquals(testCoupon.StartDate, START);
            assertEquals(testCoupon.EndDate, END);
            assertEquals(testCoupon.UnadjustedStartDate, START_UNADJUSTED);
            assertEquals(testCoupon.UnadjustedEndDate, END_UNADJUSTED);
            assertEquals(testCoupon.FixingDate, FIXING);
            assertEquals(testCoupon.PaymentDate, PAYMENT);
            assertEquals(testCoupon.Index, INDEX);
            assertEquals(testCoupon.Notional, NOTIONAL);
            assertEquals(testCoupon.YearFraction, YEAR_FRACTION);
            assertEquals(testCoupon.DayCount, ACT_360);
            assertEquals(testCoupon.Strike, 0d);
        }
        public virtual void test_builder_floor()
        {
            CmsPeriod testFloorlet = sutFloor();

            assertFalse(testFloorlet.Caplet.HasValue);
            assertEquals(testFloorlet.Floorlet.Value, STRIKE);
            assertEquals(testFloorlet.CmsPeriodType, CmsPeriodType.FLOORLET);
            assertEquals(testFloorlet.Currency, GBP);
            assertEquals(testFloorlet.StartDate, START);
            assertEquals(testFloorlet.EndDate, END);
            assertEquals(testFloorlet.UnadjustedStartDate, START_UNADJUSTED);
            assertEquals(testFloorlet.UnadjustedEndDate, END_UNADJUSTED);
            assertEquals(testFloorlet.FixingDate, FIXING);
            assertEquals(testFloorlet.PaymentDate, PAYMENT);
            assertEquals(testFloorlet.Index, INDEX);
            assertEquals(testFloorlet.Notional, NOTIONAL);
            assertEquals(testFloorlet.YearFraction, YEAR_FRACTION);
            assertEquals(testFloorlet.DayCount, ACT_360);
            assertEquals(testFloorlet.Strike, STRIKE);
        }
Beispiel #13
0
 public CmsDeltaIntegrantProvider(SabrExtrapolationReplicationCmsPeriodPricer outerInstance, CmsPeriod cmsPeriod, ResolvedSwap swap, SabrSwaptionVolatilities swaptionVolatilities, double forward, double strike, double timeToExpiry, double tenor, double cutOffStrike, double eta) : base(outerInstance, cmsPeriod, swap, swaptionVolatilities, forward, strike, timeToExpiry, tenor, cutOffStrike, eta)
 {
     this.outerInstance = outerInstance;
     this.nnp_Renamed   = nnp(forward);
 }
Beispiel #14
0
            public CmsIntegrantProvider(SabrExtrapolationReplicationCmsPeriodPricer outerInstance, CmsPeriod cmsPeriod, ResolvedSwap swap, SabrSwaptionVolatilities swaptionVolatilities, double forward, double strike, double timeToExpiry, double tenor, double cutOffStrike, double eta)
            {
                this.outerInstance = outerInstance;

                ResolvedSwapLeg fixedLeg = swap.getLegs(SwapLegType.FIXED).get(0);

                this.nbFixedPeriod      = fixedLeg.PaymentPeriods.size();
                this.nbFixedPaymentYear = (int)(long)Math.Round(1d / ((RatePaymentPeriod)fixedLeg.PaymentPeriods.get(0)).AccrualPeriods.get(0).YearFraction, MidpointRounding.AwayFromZero);
                this.tau = 1d / nbFixedPaymentYear;
                this.eta = eta;
                SabrFormulaData sabrPoint = SabrFormulaData.of(swaptionVolatilities.alpha(timeToExpiry, tenor), swaptionVolatilities.beta(timeToExpiry, tenor), swaptionVolatilities.rho(timeToExpiry, tenor), swaptionVolatilities.nu(timeToExpiry, tenor));

                this.shift             = swaptionVolatilities.shift(timeToExpiry, tenor);
                this.sabrExtrapolation = SabrExtrapolationRightFunction.of(forward + shift, timeToExpiry, sabrPoint, cutOffStrike + shift, outerInstance.mu);
                this.putCall           = cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.FLOORLET) ? PutCall.PUT : PutCall.CALL;
                this.strike            = strike;
                this.factor            = g(forward) / h(forward);
                this.g0 = new double[4];
                g0[0]   = nbFixedPeriod * tau;
                g0[1]   = -0.5 * nbFixedPeriod * (nbFixedPeriod + 1.0d) * tau * tau;
                g0[2]   = -2.0d / 3.0d * g0[1] * (nbFixedPeriod + 2.0d) * tau;
                g0[3]   = -3.0d / 4.0d * g0[2] * (nbFixedPeriod + 2.0d) * tau;
            }
Beispiel #15
0
        /// <summary>
        /// Computes the present value sensitivity to strike by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value sensitivity </returns>
        public double presentValueSensitivityStrike(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            ArgChecker.isFalse(cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON), "presentValueSensitivityStrike is not relevant for CMS coupon");
            Currency  ccy   = cmsPeriod.Currency;
            SwapIndex index = cmsPeriod.Index;

            if (provider.ValuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(0d);
            }
            ResolvedSwap  swap          = cmsPeriod.UnderlyingSwap;
            double        dfPayment     = provider.discountFactor(ccy, cmsPeriod.PaymentDate);
            ZonedDateTime valuationDate = swaptionVolatilities.ValuationDateTime;
            LocalDate     fixingDate    = cmsPeriod.FixingDate;
            double        tenor         = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);
            ZonedDateTime expiryDate    = fixingDate.atTime(index.FixingTime).atZone(index.FixingZone);
            double        expiryTime    = swaptionVolatilities.relativeTime(expiryDate);
            double        strike        = cmsPeriod.Strike;
            double        shift         = swaptionVolatilities.shift(expiryTime, tenor);

            if (!fixingDate.isAfter(valuationDate.toLocalDate()))
            {
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    double payoff = 0d;
                    switch (cmsPeriod.CmsPeriodType)
                    {
                    case CAPLET:
                        payoff = fixedRate.Value >= strike ? -1d : 0d;
                        break;

                    case FLOORLET:
                        payoff = fixedRate.Value < strike ? 1d : 0d;
                        break;

                    default:
                        throw new System.ArgumentException("unsupported CMS type");
                    }
                    return(payoff * cmsPeriod.Notional * cmsPeriod.YearFraction * dfPayment);
                }
                else if (fixingDate.isBefore(valuationDate.toLocalDate()))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            double forward = swapPricer.parRate(swap, provider);
            double eta     = index.Template.Convention.FixedLeg.DayCount.relativeYearFraction(cmsPeriod.PaymentDate, swap.StartDate);
            CmsIntegrantProvider intProv = new CmsIntegrantProvider(this, cmsPeriod, swap, swaptionVolatilities, forward, strike, expiryTime, tenor, cutOffStrike, eta);
            double factor = dfPayment * intProv.g(forward) / intProv.h(forward);
            RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(ABS_TOL, REL_TOL_STRIKE, NUM_ITER);

            double[] kpkpp = intProv.kpkpp(strike);
            double   firstPart;
            double   thirdPart;

            System.Func <double, double> integrant = intProv.integrantDualDelta();
            if (intProv.PutCall.Call)
            {
                firstPart = -kpkpp[0] * intProv.bs(strike);
                thirdPart = integrateCall(integrator, integrant, swaptionVolatilities, forward, strike, expiryTime, tenor);
            }
            else
            {
                firstPart = -kpkpp[0] * intProv.bs(strike);
                thirdPart = -integrator.integrate(integrant, -shift + ZERO_SHIFT, strike).Value;
            }
            double secondPart = intProv.k(strike) * intProv.SabrExtrapolation.priceDerivativeStrike(strike + shift, intProv.PutCall);

            return(cmsPeriod.Notional * cmsPeriod.YearFraction * factor * (firstPart + secondPart + thirdPart));
        }
Beispiel #16
0
        /// <summary>
        /// Computes the present value sensitivity to SABR parameters by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value sensitivity </returns>
        public PointSensitivityBuilder presentValueSensitivityModelParamsSabr(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            Currency      ccy           = cmsPeriod.Currency;
            SwapIndex     index         = cmsPeriod.Index;
            ResolvedSwap  swap          = cmsPeriod.UnderlyingSwap;
            double        dfPayment     = provider.discountFactor(ccy, cmsPeriod.PaymentDate);
            ZonedDateTime valuationDate = swaptionVolatilities.ValuationDateTime;
            LocalDate     fixingDate    = cmsPeriod.FixingDate;
            ZonedDateTime expiryDate    = fixingDate.atTime(index.FixingTime).atZone(index.FixingZone);
            double        tenor         = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);

            if (provider.ValuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(PointSensitivityBuilder.none());
            }
            if (!fixingDate.isAfter(valuationDate.toLocalDate()))
            {
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    return(PointSensitivityBuilder.none());
                }
                else if (fixingDate.isBefore(valuationDate.toLocalDate()))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            double expiryTime            = swaptionVolatilities.relativeTime(expiryDate);
            double shift                 = swaptionVolatilities.shift(expiryTime, tenor);
            double strikeCpn             = cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON) ? -shift : cmsPeriod.Strike;
            double forward               = swapPricer.parRate(swap, provider);
            double eta                   = index.Template.Convention.FixedLeg.DayCount.relativeYearFraction(cmsPeriod.PaymentDate, swap.StartDate);
            CmsIntegrantProvider intProv = new CmsIntegrantProvider(this, cmsPeriod, swap, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor, cutOffStrike, eta);
            double factor                = dfPayment / intProv.h(forward) * intProv.g(forward);
            double factor2               = factor * intProv.k(strikeCpn);

            double[] strikePartPrice          = intProv.SabrExtrapolation.priceAdjointSabr(Math.Max(0d, strikeCpn + shift), intProv.PutCall).Derivatives.multipliedBy(factor2).toArray();
            RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(ABS_TOL, REL_TOL_VEGA, NUM_ITER);

            double[] totalSensi = new double[4];
            for (int loopparameter = 0; loopparameter < 4; loopparameter++)
            {
                double integralPart = 0d;
                System.Func <double, double> integrant = intProv.integrantVega(loopparameter);
                try
                {
                    if (intProv.PutCall.Call)
                    {
                        integralPart = dfPayment * integrateCall(integrator, integrant, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor);
                    }
                    else
                    {
                        integralPart = -dfPayment *integrator.integrate(integrant, -shift + ZERO_SHIFT, strikeCpn);
                    }
                }
                catch (Exception e)
                {
                    throw new Exception(e);
                }
                totalSensi[loopparameter] = (strikePartPrice[loopparameter] + integralPart) * cmsPeriod.Notional * cmsPeriod.YearFraction;
            }
            SwaptionVolatilitiesName name = swaptionVolatilities.Name;

            return(PointSensitivityBuilder.of(SwaptionSabrSensitivity.of(name, expiryTime, tenor, ALPHA, ccy, totalSensi[0]), SwaptionSabrSensitivity.of(name, expiryTime, tenor, BETA, ccy, totalSensi[1]), SwaptionSabrSensitivity.of(name, expiryTime, tenor, RHO, ccy, totalSensi[2]), SwaptionSabrSensitivity.of(name, expiryTime, tenor, NU, ccy, totalSensi[3])));
        }
Beispiel #17
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the present value curve sensitivity by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value sensitivity </returns>
        public PointSensitivityBuilder presentValueSensitivityRates(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            Currency ccy = cmsPeriod.Currency;

            if (provider.ValuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(PointSensitivityBuilder.none());
            }
            SwapIndex     index         = cmsPeriod.Index;
            ResolvedSwap  swap          = cmsPeriod.UnderlyingSwap;
            double        dfPayment     = provider.discountFactor(ccy, cmsPeriod.PaymentDate);
            ZonedDateTime valuationDate = swaptionVolatilities.ValuationDateTime;
            LocalDate     fixingDate    = cmsPeriod.FixingDate;
            double        expiryTime    = swaptionVolatilities.relativeTime(fixingDate.atTime(index.FixingTime).atZone(index.FixingZone));
            double        tenor         = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);
            double        shift         = swaptionVolatilities.shift(expiryTime, tenor);
            double        strikeCpn     = cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON) ? -shift : cmsPeriod.Strike;

            if (!fixingDate.isAfter(valuationDate.toLocalDate()))
            {
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    double payoff = payOff(cmsPeriod.CmsPeriodType, strikeCpn, fixedRate.Value);
                    return(provider.discountFactors(ccy).zeroRatePointSensitivity(cmsPeriod.PaymentDate).multipliedBy(payoff * cmsPeriod.Notional * cmsPeriod.YearFraction));
                }
                else if (fixingDate.isBefore(valuationDate.toLocalDate()))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            double forward = swapPricer.parRate(swap, provider);
            double eta     = index.Template.Convention.FixedLeg.DayCount.relativeYearFraction(cmsPeriod.PaymentDate, swap.StartDate);
            CmsDeltaIntegrantProvider intProv    = new CmsDeltaIntegrantProvider(this, cmsPeriod, swap, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor, cutOffStrike, eta);
            RungeKuttaIntegrator1D    integrator = new RungeKuttaIntegrator1D(ABS_TOL, REL_TOL, NUM_ITER);

            double[] bs = intProv.bsbsp(strikeCpn);
            double[] n  = intProv.Nnp;
            double   strikePartPrice   = intProv.k(strikeCpn) * n[0] * bs[0];
            double   integralPartPrice = 0d;
            double   integralPart      = 0d;

            System.Func <double, double> integrant      = intProv.integrant();
            System.Func <double, double> integrantDelta = intProv.integrantDelta();
            try
            {
                if (intProv.PutCall.Call)
                {
                    integralPartPrice = integrateCall(integrator, integrant, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor);
                    integralPart      = dfPayment * integrateCall(integrator, integrantDelta, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor);
                }
                else
                {
                    integralPartPrice = -integrator.integrate(integrant, -shift + ZERO_SHIFT, strikeCpn).Value;
                    integralPart      = -dfPayment *integrator.integrate(integrantDelta, -shift, strikeCpn);
                }
            }
            catch (Exception e)
            {
                throw new MathException(e);
            }
            double deltaPD = strikePartPrice + integralPartPrice;

            if (cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON))
            {
                deltaPD -= shift;
            }
            deltaPD *= cmsPeriod.Notional * cmsPeriod.YearFraction;
            double strikePart = dfPayment * intProv.k(strikeCpn) * (n[1] * bs[0] + n[0] * bs[1]);
            double deltaFwd   = (strikePart + integralPart) * cmsPeriod.Notional * cmsPeriod.YearFraction;
            PointSensitivityBuilder sensiFwd = swapPricer.parRateSensitivity(swap, provider).multipliedBy(deltaFwd);
            PointSensitivityBuilder sensiDf  = provider.discountFactors(ccy).zeroRatePointSensitivity(cmsPeriod.PaymentDate).multipliedBy(deltaPD);

            return(sensiFwd.combinedWith(sensiDf));
        }
 public virtual void test_builder_nonNullCapFloor()
 {
     assertThrowsIllegalArg(() => CmsPeriod.builder().caplet(STRIKE).floorlet(STRIKE).startDate(START).endDate(END).index(INDEX).notional(NOTIONAL).yearFraction(YEAR_FRACTION).dayCount(ACT_360).build());
 }
Beispiel #19
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the present value by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value </returns>
        public CurrencyAmount presentValue(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            Currency ccy = cmsPeriod.Currency;

            if (provider.ValuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(CurrencyAmount.zero(ccy));
            }
            SwapIndex     index         = cmsPeriod.Index;
            ResolvedSwap  swap          = cmsPeriod.UnderlyingSwap;
            double        dfPayment     = provider.discountFactor(ccy, cmsPeriod.PaymentDate);
            ZonedDateTime valuationDate = swaptionVolatilities.ValuationDateTime;
            LocalDate     fixingDate    = cmsPeriod.FixingDate;
            double        expiryTime    = swaptionVolatilities.relativeTime(fixingDate.atTime(index.FixingTime).atZone(index.FixingZone));
            double        tenor         = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);
            double        shift         = swaptionVolatilities.shift(expiryTime, tenor);
            double        strikeCpn     = cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON) ? -shift : cmsPeriod.Strike;

            if (!fixingDate.isAfter(valuationDate.toLocalDate()))
            {
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    double payoff = payOff(cmsPeriod.CmsPeriodType, strikeCpn, fixedRate.Value);
                    return(CurrencyAmount.of(ccy, dfPayment * payoff * cmsPeriod.Notional * cmsPeriod.YearFraction));
                }
                else if (fixingDate.isBefore(valuationDate.toLocalDate()))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            double forward = swapPricer.parRate(swap, provider);

            if (expiryTime < MIN_TIME)
            {
                double payoff = payOff(cmsPeriod.CmsPeriodType, strikeCpn, forward);
                return(CurrencyAmount.of(ccy, dfPayment * payoff * cmsPeriod.Notional * cmsPeriod.YearFraction));
            }
            double eta = index.Template.Convention.FixedLeg.DayCount.relativeYearFraction(cmsPeriod.PaymentDate, swap.StartDate);
            CmsIntegrantProvider intProv = new CmsIntegrantProvider(this, cmsPeriod, swap, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor, cutOffStrike, eta);
            double factor     = dfPayment / intProv.h(forward) * intProv.g(forward);
            double strikePart = factor * intProv.k(strikeCpn) * intProv.bs(strikeCpn);
            RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(ABS_TOL, REL_TOL, NUM_ITER);
            double integralPart = 0d;

            System.Func <double, double> integrant = intProv.integrant();
            try
            {
                if (intProv.PutCall.Call)
                {
                    integralPart = dfPayment * integrateCall(integrator, integrant, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor);
                }
                else
                {
                    integralPart = -dfPayment *integrator.integrate(integrant, -shift + ZERO_SHIFT, strikeCpn);
                }
            }
            catch (Exception e)
            {
                throw new MathException(e);
            }
            double priceCMS = (strikePart + integralPart);

            if (cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON))
            {
                priceCMS -= dfPayment * shift;
            }
            priceCMS *= cmsPeriod.Notional * cmsPeriod.YearFraction;
            return(CurrencyAmount.of(ccy, priceCMS));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the present value by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value </returns>
        public CurrencyAmount presentValue(CmsPeriod cmsPeriod, RatesProvider provider, SwaptionVolatilities swaptionVolatilities)
        {
            Currency  ccy           = cmsPeriod.Currency;
            LocalDate valuationDate = provider.ValuationDate;

            if (valuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(CurrencyAmount.zero(ccy));
            }
            LocalDate fixingDate = cmsPeriod.FixingDate;
            double    dfPayment  = provider.discountFactor(ccy, cmsPeriod.PaymentDate);

            if (!fixingDate.isAfter(valuationDate))
            {     // Using fixing
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    double payoff = 0d;
                    switch (cmsPeriod.CmsPeriodType)
                    {
                    case CAPLET:
                        payoff = Math.Max(fixedRate.Value - cmsPeriod.Strike, 0d);
                        break;

                    case FLOORLET:
                        payoff = Math.Max(cmsPeriod.Strike - fixedRate.Value, 0d);
                        break;

                    case COUPON:
                        payoff = fixedRate.Value;
                        break;

                    default:
                        throw new System.ArgumentException("unsupported CMS type");
                    }
                    return(CurrencyAmount.of(ccy, payoff * dfPayment * cmsPeriod.Notional * cmsPeriod.YearFraction));
                }
                else if (fixingDate.isBefore(valuationDate))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            if (!cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON))
            {
                throw new System.ArgumentException("Unable to price cap or floor in this pricer");
            }
            // Using forward
            SwapIndex        index              = cmsPeriod.Index;
            ResolvedSwap     swap               = cmsPeriod.UnderlyingSwap;
            ResolvedSwapLeg  fixedLeg           = swap.getLegs(SwapLegType.FIXED).get(0);
            int              nbFixedPaymentYear = (int)(long)Math.Round(1d / ((RatePaymentPeriod)fixedLeg.PaymentPeriods.get(0)).AccrualPeriods.get(0).YearFraction, MidpointRounding.AwayFromZero);
            int              nbFixedPeriod      = fixedLeg.PaymentPeriods.size();
            double           forward            = swapPricer.parRate(swap, provider);
            double           tenor              = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);
            double           expiryTime         = swaptionVolatilities.relativeTime(fixingDate.atTime(index.FixingTime).atZone(index.FixingZone));
            double           volatility         = swaptionVolatilities.volatility(expiryTime, tenor, forward, forward);
            ValueDerivatives annuityDerivatives = swapPricer.LegPricer.annuityCash2(nbFixedPaymentYear, nbFixedPeriod, volatility);
            double           forwardAdjustment  = -0.5 * forward * forward * volatility * volatility * expiryTime * annuityDerivatives.getDerivative(1) / annuityDerivatives.getDerivative(0);

            return(CurrencyAmount.of(ccy, (forward + forwardAdjustment) * dfPayment * cmsPeriod.Notional * cmsPeriod.YearFraction));
        }