// calculate the last fixing date
        private LocalDate calculateLastFixingDate(LocalDate valuationDate, ReferenceData refData)
        {
            SwapTrade                 trade                = template.createTrade(valuationDate, BuySell.BUY, 1, 1, refData);
            SwapLeg                   inflationLeg         = trade.Product.getLegs(SwapLegType.INFLATION).get(0);
            ResolvedSwapLeg           inflationLegExpanded = inflationLeg.resolve(refData);
            IList <SwapPaymentPeriod> periods              = inflationLegExpanded.PaymentPeriods;
            int nbPeriods = periods.Count;
            RatePaymentPeriod         lastPeriod = (RatePaymentPeriod)periods[nbPeriods - 1];
            IList <RateAccrualPeriod> accruals   = lastPeriod.AccrualPeriods;
            int nbAccruals = accruals.Count;
            RateAccrualPeriod lastAccrual = accruals[nbAccruals - 1];

            if (lastAccrual.RateComputation is InflationMonthlyRateComputation)
            {
                return(((InflationMonthlyRateComputation)lastAccrual.RateComputation).EndObservation.FixingMonth.atEndOfMonth());
            }
            if (lastAccrual.RateComputation is InflationInterpolatedRateComputation)
            {
                return(((InflationInterpolatedRateComputation)lastAccrual.RateComputation).EndSecondObservation.FixingMonth.atEndOfMonth());
            }
            if (lastAccrual.RateComputation is InflationEndMonthRateComputation)
            {
                return(((InflationEndMonthRateComputation)lastAccrual.RateComputation).EndObservation.FixingMonth.atEndOfMonth());
            }
            if (lastAccrual.RateComputation is InflationEndInterpolatedRateComputation)
            {
                return(((InflationEndInterpolatedRateComputation)lastAccrual.RateComputation).EndSecondObservation.FixingMonth.atEndOfMonth());
            }
            throw new System.ArgumentException("Rate computation type not supported for last fixing date of an inflation swap.");
        }
Пример #2
0
        /// <summary>
        /// Computes cash flow equivalent of Ibor leg.
        /// <para>
        /// The return type is {@code ResolvedSwapLeg} in which individual payments are
        /// represented in terms of {@code NotionalExchange}.
        ///
        /// </para>
        /// </summary>
        /// <param name="iborLeg">  the Ibor leg </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <returns> the cash flow equivalent </returns>
        public static ResolvedSwapLeg cashFlowEquivalentIborLeg(ResolvedSwapLeg iborLeg, RatesProvider ratesProvider)
        {
            ArgChecker.isTrue(iborLeg.Type.Equals(SwapLegType.IBOR), "Leg type should be IBOR");
            ArgChecker.isTrue(iborLeg.PaymentEvents.Empty, "PaymentEvent should be empty");
            IList <NotionalExchange> paymentEvents = new List <NotionalExchange>();

            foreach (SwapPaymentPeriod paymentPeriod in iborLeg.PaymentPeriods)
            {
                ArgChecker.isTrue(paymentPeriod is RatePaymentPeriod, "rate payment should be RatePaymentPeriod");
                RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod)paymentPeriod;
                ArgChecker.isTrue(ratePaymentPeriod.AccrualPeriods.size() == 1, "rate payment should not be compounding");
                RateAccrualPeriod    rateAccrualPeriod = ratePaymentPeriod.AccrualPeriods.get(0);
                CurrencyAmount       notional          = ratePaymentPeriod.NotionalAmount;
                LocalDate            paymentDate       = ratePaymentPeriod.PaymentDate;
                IborIndexObservation obs             = ((IborRateComputation)rateAccrualPeriod.RateComputation).Observation;
                IborIndex            index           = obs.Index;
                LocalDate            fixingStartDate = obs.EffectiveDate;
                double           fixingYearFraction  = obs.YearFraction;
                double           beta     = (1d + fixingYearFraction * ratesProvider.iborIndexRates(index).rate(obs)) * ratesProvider.discountFactor(paymentPeriod.Currency, paymentPeriod.PaymentDate) / ratesProvider.discountFactor(paymentPeriod.Currency, fixingStartDate);
                double           ycRatio  = rateAccrualPeriod.YearFraction / fixingYearFraction;
                NotionalExchange payStart = NotionalExchange.of(notional.multipliedBy(beta * ycRatio), fixingStartDate);
                NotionalExchange payEnd   = NotionalExchange.of(notional.multipliedBy(-ycRatio), paymentDate);
                paymentEvents.Add(payStart);
                paymentEvents.Add(payEnd);
            }
            ResolvedSwapLeg leg = ResolvedSwapLeg.builder().paymentEvents(paymentEvents).payReceive(PayReceive.RECEIVE).type(SwapLegType.OTHER).build();

            return(leg);
        }
        /// <summary>
        /// Calculates the strike.
        /// </summary>
        /// <param name="fixedLeg">  the fixed leg </param>
        /// <returns> the strike </returns>
        protected internal virtual double calculateStrike(ResolvedSwapLeg fixedLeg)
        {
            SwapPaymentPeriod paymentPeriod = fixedLeg.PaymentPeriods.get(0);

            ArgChecker.isTrue(paymentPeriod is RatePaymentPeriod, "Payment period must be RatePaymentPeriod");
            RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod)paymentPeriod;
            // compounding is caught when par rate is computed
            RateComputation rateComputation = ratePaymentPeriod.AccrualPeriods.get(0).RateComputation;

            ArgChecker.isTrue(rateComputation is FixedRateComputation, "Swap leg must be fixed leg");
            return(((FixedRateComputation)rateComputation).Rate);
        }
Пример #4
0
        /// <summary>
        /// Computes the derivative of the conventional cash annuity with respect to the yield from a swap leg.
        /// <para>
        /// The computation is relevant only for standard swaps with constant notional and regular payments.
        /// The swap leg must be a fixed leg. However, this is not checked internally.
        ///
        /// </para>
        /// </summary>
        /// <param name="fixedLeg">  the fixed leg of the swap </param>
        /// <param name="yield">  the yield </param>
        /// <returns> the cash annuity </returns>
        public virtual ValueDerivatives annuityCashDerivative(ResolvedSwapLeg fixedLeg, double yield)
        {
            int nbFixedPeriod = fixedLeg.PaymentPeriods.size();
            SwapPaymentPeriod paymentPeriod = fixedLeg.PaymentPeriods.get(0);

            ArgChecker.isTrue(paymentPeriod is RatePaymentPeriod, "payment period should be RatePaymentPeriod");
            RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod)paymentPeriod;
            int              nbFixedPaymentYear = (int)(long)Math.Round(1d / ratePaymentPeriod.DayCount.yearFraction(ratePaymentPeriod.StartDate, ratePaymentPeriod.EndDate), MidpointRounding.AwayFromZero);
            double           notional           = Math.Abs(ratePaymentPeriod.Notional);
            ValueDerivatives annuityUnit        = annuityCash1(nbFixedPaymentYear, nbFixedPeriod, yield);

            return(ValueDerivatives.of(annuityUnit.Value * notional, annuityUnit.Derivatives.multipliedBy(notional)));
        }
Пример #5
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the conventional cash annuity from a swap leg.
        /// <para>
        /// The computation is relevant only for standard swaps with constant notional and regular payments.
        /// The swap leg must be a fixed leg. However, this is not checked internally.
        ///
        /// </para>
        /// </summary>
        /// <param name="fixedLeg">  the fixed leg of the swap </param>
        /// <param name="yield">  the yield </param>
        /// <returns> the cash annuity </returns>
        public virtual double annuityCash(ResolvedSwapLeg fixedLeg, double yield)
        {
            int nbFixedPeriod = fixedLeg.PaymentPeriods.size();
            SwapPaymentPeriod paymentPeriod = fixedLeg.PaymentPeriods.get(0);

            ArgChecker.isTrue(paymentPeriod is RatePaymentPeriod, "payment period should be RatePaymentPeriod");
            RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod)paymentPeriod;
            int    nbFixedPaymentYear           = (int)(long)Math.Round(1d / ratePaymentPeriod.DayCount.yearFraction(ratePaymentPeriod.StartDate, ratePaymentPeriod.EndDate), MidpointRounding.AwayFromZero);
            double notional    = Math.Abs(ratePaymentPeriod.Notional);
            double annuityCash = notional * this.annuityCash(nbFixedPaymentYear, nbFixedPeriod, yield);

            return(annuityCash);
        }
Пример #6
0
        // calculate the last fixing date
        private LocalDate calculateLastFixingDate(LocalDate valuationDate, ReferenceData refData)
        {
            SwapTrade                 trade           = template.createTrade(valuationDate, BuySell.BUY, 1, 1, refData);
            SwapLeg                   iborLeg         = trade.Product.getLegs(SwapLegType.IBOR).get(0);
            ResolvedSwapLeg           iborLegExpanded = iborLeg.resolve(refData);
            IList <SwapPaymentPeriod> periods         = iborLegExpanded.PaymentPeriods;
            int nbPeriods = periods.Count;
            RatePaymentPeriod         lastPeriod = (RatePaymentPeriod)periods[nbPeriods - 1];
            IList <RateAccrualPeriod> accruals   = lastPeriod.AccrualPeriods;
            int nbAccruals           = accruals.Count;
            IborRateComputation ibor = (IborRateComputation)accruals[nbAccruals - 1].RateComputation;

            return(ibor.FixingDate);
        }
Пример #7
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the par rate for swaps with a fixed leg.
        /// <para>
        /// The par rate is the common rate on all payments of the fixed leg for which the total swap present value is 0.
        /// </para>
        /// <para>
        /// At least one leg must be a fixed leg. The par rate will be computed with respect to the first fixed leg
        /// in which all the payments are fixed payments with a unique accrual period (no compounding) and no FX reset.
        /// If the fixed leg is compounding, the par rate is computed only when the number of fixed coupon payments is 1 and
        /// accrual factor of each sub-period is 1
        ///
        /// </para>
        /// </summary>
        /// <param name="swap">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the par rate </returns>
        public virtual double parRate(ResolvedSwap swap, RatesProvider provider)
        {
            // find fixed leg
            ResolvedSwapLeg fixedLeg    = this.fixedLeg(swap);
            Currency        ccyFixedLeg = fixedLeg.Currency;
            // other payments (not fixed leg coupons) converted in fixed leg currency
            double otherLegsConvertedPv = 0.0;

            foreach (ResolvedSwapLeg leg in swap.Legs)
            {
                if (leg != fixedLeg)
                {
                    double pvLocal = legPricer.presentValueInternal(leg, provider);
                    otherLegsConvertedPv += (pvLocal * provider.fxRate(leg.Currency, ccyFixedLeg));
                }
            }
            double fixedLegEventsPv = legPricer.presentValueEventsInternal(fixedLeg, provider);

            if (fixedLeg.PaymentPeriods.size() > 1)
            {     // try multiperiod par-rate
                  // PVBP
                double pvbpFixedLeg = legPricer.pvbp(fixedLeg, provider);
                // Par rate
                return(-(otherLegsConvertedPv + fixedLegEventsPv) / pvbpFixedLeg);
            }
            SwapPaymentPeriod firstPeriod = fixedLeg.PaymentPeriods.get(0);

            ArgChecker.isTrue(firstPeriod is RatePaymentPeriod, "PaymentPeriod must be instance of RatePaymentPeriod");
            RatePaymentPeriod payment = (RatePaymentPeriod)firstPeriod;

            if (payment.AccrualPeriods.size() == 1)
            {     // no compounding
                  // PVBP
                double pvbpFixedLeg = legPricer.pvbp(fixedLeg, provider);
                // Par rate
                return(-(otherLegsConvertedPv + fixedLegEventsPv) / pvbpFixedLeg);
            }
            // try Compounding
            Triple <bool, int, double> fixedCompounded = checkFixedCompounded(fixedLeg);

            ArgChecker.isTrue(fixedCompounded.First, "Swap should have a fixed leg and for one payment it should be based on compunding witout spread.");
            double notional = payment.Notional;
            double df       = provider.discountFactor(ccyFixedLeg, payment.PaymentDate);

            return(Math.Pow(-(otherLegsConvertedPv + fixedLegEventsPv) / (notional * df) + 1.0d, 1.0 / fixedCompounded.Second) - 1.0d);
        }
Пример #8
0
        // Checks if the leg is a fixed leg with one payment and compounding
        // This type of leg is used in zero-coupon inflation swaps
        // When returning a 'true' for the first element, the second element is the number of periods which are used in
        //   par rate/spread computation and the third element is the common fixed rate
        private Triple <bool, int, double> checkFixedCompounded(ResolvedSwapLeg leg)
        {
            if (leg.PaymentEvents.size() != 0)
            {
                return(Triple.of(false, 0, 0.0d));  // No event
            }
            RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod)leg.PaymentPeriods.get(0);

            if (ratePaymentPeriod.CompoundingMethod == CompoundingMethod.NONE)
            {
                return(Triple.of(false, 0, 0.0d));  // Should be compounded
            }
            ImmutableList <RateAccrualPeriod> accrualPeriods = ratePaymentPeriod.AccrualPeriods;
            int    nbAccrualPeriods = accrualPeriods.size();
            double fixedRate        = 0;

            for (int i = 0; i < nbAccrualPeriods; i++)
            {
                if (!(accrualPeriods.get(i).RateComputation is FixedRateComputation))
                {
                    return(Triple.of(false, 0, 0.0d));    // Should be fixed period
                }
                if ((i > 0) && (((FixedRateComputation)accrualPeriods.get(i).RateComputation).Rate != fixedRate))
                {
                    return(Triple.of(false, 0, 0.0d));    // All fixed rates should be the same
                }
                fixedRate = ((FixedRateComputation)accrualPeriods.get(i).RateComputation).Rate;
                if (accrualPeriods.get(i).Spread != 0)
                {
                    return(Triple.of(false, 0, 0.0d));    // Should have no spread
                }
                if (accrualPeriods.get(i).Gearing != 1.0d)
                {
                    return(Triple.of(false, 0, 0.0d));    // Should have a gearing of 1.
                }
                if (accrualPeriods.get(i).YearFraction != 1.0d)
                {
                    return(Triple.of(false, 0, 0.0d));    // Should have a year fraction of 1.
                }
            }
            return(Triple.of(true, nbAccrualPeriods, fixedRate));
        }
Пример #9
0
        /// <summary>
        /// Computes cash flow equivalent and sensitivity of fixed leg.
        /// <para>
        /// The return type is a map of {@code NotionalExchange} and {@code PointSensitivityBuilder}.
        ///
        /// </para>
        /// </summary>
        /// <param name="fixedLeg">  the fixed leg </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <returns> the cash flow equivalent and sensitivity </returns>
        public static ImmutableMap <Payment, PointSensitivityBuilder> cashFlowEquivalentAndSensitivityFixedLeg(ResolvedSwapLeg fixedLeg, RatesProvider ratesProvider)
        {
            ArgChecker.isTrue(fixedLeg.Type.Equals(SwapLegType.FIXED), "Leg type should be FIXED");
            ArgChecker.isTrue(fixedLeg.PaymentEvents.Empty, "PaymentEvent should be empty");
            IDictionary <Payment, PointSensitivityBuilder> res = new Dictionary <Payment, PointSensitivityBuilder>();

            foreach (SwapPaymentPeriod paymentPeriod in fixedLeg.PaymentPeriods)
            {
                ArgChecker.isTrue(paymentPeriod is RatePaymentPeriod, "rate payment should be RatePaymentPeriod");
                RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod)paymentPeriod;
                ArgChecker.isTrue(ratePaymentPeriod.AccrualPeriods.size() == 1, "rate payment should not be compounding");
                RateAccrualPeriod rateAccrualPeriod = ratePaymentPeriod.AccrualPeriods.get(0);
                double            factor            = rateAccrualPeriod.YearFraction * ((FixedRateComputation)rateAccrualPeriod.RateComputation).Rate;
                CurrencyAmount    notional          = ratePaymentPeriod.NotionalAmount.multipliedBy(factor);
                LocalDate         paymentDate       = ratePaymentPeriod.PaymentDate;
                Payment           pay = Payment.of(notional, paymentDate);
                res[pay] = PointSensitivityBuilder.none();
            }
            return(ImmutableMap.copyOf(res));
        }
Пример #10
0
        /// <summary>
        /// Computes cash flow equivalent of fixed leg.
        /// <para>
        /// The return type is {@code ResolvedSwapLeg} in which individual payments are
        /// represented in terms of {@code NotionalExchange}.
        ///
        /// </para>
        /// </summary>
        /// <param name="fixedLeg">  the fixed leg </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <returns> the cash flow equivalent </returns>
        public static ResolvedSwapLeg cashFlowEquivalentFixedLeg(ResolvedSwapLeg fixedLeg, RatesProvider ratesProvider)
        {
            ArgChecker.isTrue(fixedLeg.Type.Equals(SwapLegType.FIXED), "Leg type should be FIXED");
            ArgChecker.isTrue(fixedLeg.PaymentEvents.Empty, "PaymentEvent should be empty");
            IList <NotionalExchange> paymentEvents = new List <NotionalExchange>();

            foreach (SwapPaymentPeriod paymentPeriod in fixedLeg.PaymentPeriods)
            {
                ArgChecker.isTrue(paymentPeriod is RatePaymentPeriod, "rate payment should be RatePaymentPeriod");
                RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod)paymentPeriod;
                ArgChecker.isTrue(ratePaymentPeriod.AccrualPeriods.size() == 1, "rate payment should not be compounding");
                RateAccrualPeriod rateAccrualPeriod = ratePaymentPeriod.AccrualPeriods.get(0);
                double            factor            = rateAccrualPeriod.YearFraction * ((FixedRateComputation)rateAccrualPeriod.RateComputation).Rate;
                CurrencyAmount    notional          = ratePaymentPeriod.NotionalAmount.multipliedBy(factor);
                LocalDate         paymentDate       = ratePaymentPeriod.PaymentDate;
                NotionalExchange  pay = NotionalExchange.of(notional, paymentDate);
                paymentEvents.Add(pay);
            }
            ResolvedSwapLeg leg = ResolvedSwapLeg.builder().paymentEvents(paymentEvents).payReceive(PayReceive.RECEIVE).type(SwapLegType.OTHER).build();

            return(leg);
        }
Пример #11
0
        /// <summary>
        /// Computes cash flow equivalent and sensitivity of Ibor leg.
        /// <para>
        /// The return type is a map of {@code NotionalExchange} and {@code PointSensitivityBuilder}.
        ///
        /// </para>
        /// </summary>
        /// <param name="iborLeg">  the Ibor leg </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <returns> the cash flow equivalent and sensitivity </returns>
        public static ImmutableMap <Payment, PointSensitivityBuilder> cashFlowEquivalentAndSensitivityIborLeg(ResolvedSwapLeg iborLeg, RatesProvider ratesProvider)
        {
            ArgChecker.isTrue(iborLeg.Type.Equals(SwapLegType.IBOR), "Leg type should be IBOR");
            ArgChecker.isTrue(iborLeg.PaymentEvents.Empty, "PaymentEvent should be empty");
            IDictionary <Payment, PointSensitivityBuilder> res = new Dictionary <Payment, PointSensitivityBuilder>();

            foreach (SwapPaymentPeriod paymentPeriod in iborLeg.PaymentPeriods)
            {
                ArgChecker.isTrue(paymentPeriod is RatePaymentPeriod, "rate payment should be RatePaymentPeriod");
                RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod)paymentPeriod;
                ArgChecker.isTrue(ratePaymentPeriod.AccrualPeriods.size() == 1, "rate payment should not be compounding");
                RateAccrualPeriod    rateAccrualPeriod = ratePaymentPeriod.AccrualPeriods.get(0);
                CurrencyAmount       notional          = ratePaymentPeriod.NotionalAmount;
                LocalDate            paymentDate       = ratePaymentPeriod.PaymentDate;
                IborIndexObservation obs             = ((IborRateComputation)rateAccrualPeriod.RateComputation).Observation;
                IborIndex            index           = obs.Index;
                LocalDate            fixingStartDate = obs.EffectiveDate;
                double fixingYearFraction            = obs.YearFraction;

                double  factorIndex = (1d + fixingYearFraction * ratesProvider.iborIndexRates(index).rate(obs));
                double  dfPayment   = ratesProvider.discountFactor(paymentPeriod.Currency, paymentPeriod.PaymentDate);
                double  dfStart     = ratesProvider.discountFactor(paymentPeriod.Currency, fixingStartDate);
                double  beta        = factorIndex * dfPayment / dfStart;
                double  ycRatio     = rateAccrualPeriod.YearFraction / fixingYearFraction;
                Payment payStart    = Payment.of(notional.multipliedBy(beta * ycRatio), fixingStartDate);
                Payment payEnd      = Payment.of(notional.multipliedBy(-ycRatio), paymentDate);
                double  factor      = ycRatio * notional.Amount / dfStart;

                PointSensitivityBuilder factorIndexSensi     = ratesProvider.iborIndexRates(index).ratePointSensitivity(obs).multipliedBy(fixingYearFraction * dfPayment * factor);
                PointSensitivityBuilder dfPaymentSensitivity = ratesProvider.discountFactors(paymentPeriod.Currency).zeroRatePointSensitivity(paymentPeriod.PaymentDate).multipliedBy(factorIndex * factor);
                PointSensitivityBuilder dfStartSensitivity   = ratesProvider.discountFactors(paymentPeriod.Currency).zeroRatePointSensitivity(fixingStartDate).multipliedBy(-factorIndex * dfPayment * factor / dfStart);
                res[payStart] = factorIndexSensi.combinedWith(dfPaymentSensitivity).combinedWith(dfStartSensitivity);
                res[payEnd]   = PointSensitivityBuilder.none();
            }
            return(ImmutableMap.copyOf(res));
        }