Ejemplo n.º 1
0
        /// <summary>
        /// Calculates the par spread curve sensitivity for a swap.
        /// <para>
        /// The par spread is the common spread on all payments of the first leg for which the total swap present value is 0.
        /// </para>
        /// <para>
        /// The par spread is computed with respect to the first leg. For that leg, all the payments have a unique
        /// accrual period (no compounding) and no FX reset.
        ///
        /// </para>
        /// </summary>
        /// <param name="swap">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the par spread curve sensitivity of the swap product </returns>
        public virtual PointSensitivityBuilder parSpreadSensitivity(ResolvedSwap swap, RatesProvider provider)
        {
            ResolvedSwapLeg         referenceLeg    = swap.Legs.get(0);
            Currency                ccyReferenceLeg = referenceLeg.Currency;
            double                  convertedPv     = presentValue(swap, ccyReferenceLeg, provider).Amount;
            PointSensitivityBuilder convertedPvDr   = presentValueSensitivity(swap, ccyReferenceLeg, provider);
            // try one payment compounding, typically for inflation swaps
            Triple <bool, int, double> fixedCompounded = checkFixedCompounded(referenceLeg);

            if (fixedCompounded.First)
            {
                double df = provider.discountFactor(ccyReferenceLeg, referenceLeg.PaymentPeriods.get(0).PaymentDate);
                PointSensitivityBuilder dfDr = provider.discountFactors(ccyReferenceLeg).zeroRatePointSensitivity(referenceLeg.PaymentPeriods.get(0).PaymentDate);
                double referenceConvertedPv  = legPricer.presentValue(referenceLeg, provider).Amount;
                PointSensitivityBuilder referenceConvertedPvDr = legPricer.presentValueSensitivity(referenceLeg, provider);
                double notional = ((RatePaymentPeriod)referenceLeg.PaymentPeriods.get(0)).Notional;
                PointSensitivityBuilder dParSpreadDr = convertedPvDr.combinedWith(referenceConvertedPvDr.multipliedBy(-1)).multipliedBy(-1.0d / (df * notional)).combinedWith(dfDr.multipliedBy((convertedPv - referenceConvertedPv) / (df * df * notional))).multipliedBy(1.0d / fixedCompounded.Second * Math.Pow(-(convertedPv - referenceConvertedPv) / (df * notional) + 1.0d, 1.0d / fixedCompounded.Second - 1.0d));
                return(dParSpreadDr);
            }
            double pvbp = legPricer.pvbp(referenceLeg, provider);
            // Backward sweep
            double convertedPvBar          = -1d / pvbp;
            double pvbpBar                 = convertedPv / (pvbp * pvbp);
            PointSensitivityBuilder pvbpDr = legPricer.pvbpSensitivity(referenceLeg, provider);

            return(convertedPvDr.multipliedBy(convertedPvBar).combinedWith(pvbpDr.multipliedBy(pvbpBar)));
        }
Ejemplo n.º 2
0
        //-------------------------------------------------------------------------
        public virtual void test_presentValue()
        {
            CurrencyAmount computedRec = PRICER.presentValue(SWAPTION_REC_LONG, RATE_PROVIDER, HW_PROVIDER);
            CurrencyAmount computedPay = PRICER.presentValue(SWAPTION_PAY_SHORT, RATE_PROVIDER, HW_PROVIDER);
            SwapPaymentEventPricer <SwapPaymentEvent> paymentEventPricer = SwapPaymentEventPricer.standard();
            ResolvedSwapLeg cashFlowEquiv = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(RSWAP_REC, RATE_PROVIDER);
            LocalDate       expiryDate    = MATURITY.toLocalDate();
            int             nPayments     = cashFlowEquiv.PaymentEvents.size();

            double[] alpha = new double[nPayments];
            double[] discountedCashFlow = new double[nPayments];
            for (int loopcf = 0; loopcf < nPayments; loopcf++)
            {
                SwapPaymentEvent payment = cashFlowEquiv.PaymentEvents.get(loopcf);
                alpha[loopcf] = HW_PROVIDER.alpha(RATE_PROVIDER.ValuationDate, expiryDate, expiryDate, payment.PaymentDate);
                discountedCashFlow[loopcf] = paymentEventPricer.presentValue(payment, RATE_PROVIDER);
            }
            double omegaPay    = -1d;
            double kappa       = HW_PROVIDER.Model.kappa(DoubleArray.copyOf(discountedCashFlow), DoubleArray.copyOf(alpha));
            double expectedRec = 0.0;
            double expectedPay = 0.0;

            for (int loopcf = 0; loopcf < nPayments; loopcf++)
            {
                expectedRec += discountedCashFlow[loopcf] * NORMAL.getCDF((kappa + alpha[loopcf]));
                expectedPay += discountedCashFlow[loopcf] * NORMAL.getCDF(omegaPay * (kappa + alpha[loopcf]));
            }
            assertEquals(computedRec.Currency, EUR);
            assertEquals(computedRec.Amount, expectedRec, NOTIONAL * TOL);
            assertEquals(computedPay.Currency, EUR);
            assertEquals(computedPay.Amount, expectedPay, NOTIONAL * TOL);
        }
        //-----------------------------------------------------------------------
        public virtual void fixedSwapLeg()
        {
            // a PeriodicSchedule generates a schedule of accrual periods
            // - interest is accrued every 3 months from 2014-02-12 to 2014-07-31
            // - accrual period dates are adjusted "modified following" using the "GBLO" holiday calendar
            // - there will be a long initial stub
            // - the regular accrual period dates will be at the end-of-month
            PeriodicSchedule accrualSchedule = PeriodicSchedule.builder().startDate(LocalDate.of(2014, 2, 12)).endDate(LocalDate.of(2016, 7, 31)).businessDayAdjustment(BusinessDayAdjustment.of(MODIFIED_FOLLOWING, HolidayCalendarIds.GBLO)).frequency(Frequency.P3M).stubConvention(StubConvention.LONG_INITIAL).rollConvention(RollConventions.EOM).build();
            // a PaymentSchedule generates a schedule of payment periods, based on the accrual schedule
            // - payments are every 6 months
            // - payments are 2 business days after the end of the period
            // - straight compounding is used (the payments are less frequent than the accrual, so compounding occurs)
            PaymentSchedule paymentSchedule = PaymentSchedule.builder().paymentFrequency(Frequency.P6M).paymentRelativeTo(PaymentRelativeTo.PERIOD_END).paymentDateOffset(DaysAdjustment.ofBusinessDays(2, HolidayCalendarIds.GBLO)).compoundingMethod(CompoundingMethod.STRAIGHT).build();
            // a NotionalSchedule generates a schedule of notional amounts, based on the payment schedule
            // - in this simple case the notional is 1 million GBP and does not change
            NotionalSchedule notionalSchedule = NotionalSchedule.of(Currency.GBP, 1_000_000);
            // a RateCalculationSwapLeg can represent a fixed or floating swap leg
            // - a FixedRateCalculation is used to represent a fixed rate
            // - the "Act/Act ISDA" day count is used
            // - the rate starts at 0.8% and reduces to 0.7%
            RateCalculationSwapLeg swapLeg = RateCalculationSwapLeg.builder().payReceive(PayReceive.PAY).accrualSchedule(accrualSchedule).paymentSchedule(paymentSchedule).notionalSchedule(notionalSchedule).calculation(FixedRateCalculation.builder().dayCount(DayCounts.ACT_ACT_ISDA).rate(ValueSchedule.of(0.008, ValueStep.of(LocalDate.of(2015, 1, 31), ValueAdjustment.ofReplace(0.007)))).build()).build();
            // a ResolvedSwapLeg has all the dates of the cash flows
            // it remains valid so long as the holiday calendar does not change
            ResolvedSwapLeg resolvedLeg = swapLeg.resolve(ReferenceData.standard());

            Console.WriteLine("===== Fixed =====");
            Console.WriteLine(JodaBeanSer.PRETTY.xmlWriter().write(swapLeg));
            Console.WriteLine();
            Console.WriteLine("===== Fixed resolved =====");
            Console.WriteLine(JodaBeanSer.PRETTY.xmlWriter().write(resolvedLeg));
            Console.WriteLine();
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Calculates the present value of the swaption product.
        /// <para>
        /// The result is expressed using the currency of the swapion.
        ///
        /// </para>
        /// </summary>
        /// <param name="swaption">  the product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="hwProvider">  the Hull-White model parameter provider </param>
        /// <returns> the present value </returns>
        public virtual CurrencyAmount presentValue(ResolvedSwaption swaption, RatesProvider ratesProvider, HullWhiteOneFactorPiecewiseConstantParametersProvider hwProvider)
        {
            validate(swaption, ratesProvider, hwProvider);
            ResolvedSwap swap       = swaption.Underlying;
            LocalDate    expiryDate = swaption.ExpiryDate;

            if (expiryDate.isBefore(ratesProvider.ValuationDate))
            {     // Option has expired already
                return(CurrencyAmount.of(swap.Legs.get(0).Currency, 0d));
            }
            ResolvedSwapLeg cashFlowEquiv = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap, ratesProvider);
            int             nPayments     = cashFlowEquiv.PaymentEvents.size();

            double[] alpha = new double[nPayments];
            double[] discountedCashFlow = new double[nPayments];
            for (int loopcf = 0; loopcf < nPayments; loopcf++)
            {
                NotionalExchange payment      = (NotionalExchange)cashFlowEquiv.PaymentEvents.get(loopcf);
                LocalDate        maturityDate = payment.PaymentDate;
                alpha[loopcf] = hwProvider.alpha(ratesProvider.ValuationDate, expiryDate, expiryDate, maturityDate);
                discountedCashFlow[loopcf] = paymentPricer.presentValueAmount(payment.Payment, ratesProvider);
            }
            double omega = (swap.getLegs(SwapLegType.FIXED).get(0).PayReceive.Pay ? -1d : 1d);
            double kappa = computeKappa(hwProvider, discountedCashFlow, alpha, omega);
            double pv    = 0.0;

            for (int loopcf = 0; loopcf < nPayments; loopcf++)
            {
                pv += discountedCashFlow[loopcf] * NORMAL.getCDF(omega * (kappa + alpha[loopcf]));
            }
            return(CurrencyAmount.of(cashFlowEquiv.Currency, pv * (swaption.LongShort.Long ? 1d : -1d)));
        }
        // 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.");
        }
Ejemplo n.º 6
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 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);
            double           pvbp          = SwapPricer.LegPricer.pvbp(fixedLeg, ratesProvider);
            double           strike        = SwapPricer.LegPricer.couponEquivalent(fixedLeg, ratesProvider, pvbp);
            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;
            // Payer at strike is exercise when rate > strike, i.e. call on rate
            // Backward sweep
            PointSensitivityBuilder pvbpDr    = SwapPricer.LegPricer.pvbpSensitivity(fixedLeg, ratesProvider);
            PointSensitivityBuilder forwardDr = SwapPricer.parRateSensitivity(underlying, ratesProvider);
            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);
            double sign          = swaption.LongShort.sign();

            return(pvbpDr.multipliedBy(price * sign * Math.Sign(pvbp)).combinedWith(forwardDr.multipliedBy((delta + vega * volatilityAdj.getDerivative(0)) * Math.Abs(pvbp) * sign)));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity to the SABR model parameters of the swaption product.
        /// <para>
        /// The sensitivity of the present value to the SABR model parameters, alpha, beta, rho and nu.
        ///
        /// </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 SABR model parameters </returns>
        public virtual PointSensitivityBuilder presentValueSensitivityModelParamsSabr(ResolvedSwaption swaption, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            validate(swaption, ratesProvider, swaptionVolatilities);
            double          expiry     = swaptionVolatilities.relativeTime(swaption.Expiry);
            ResolvedSwap    underlying = swaption.Underlying;
            ResolvedSwapLeg fixedLeg   = this.fixedLeg(underlying);
            double          tenor      = swaptionVolatilities.tenor(fixedLeg.StartDate, fixedLeg.EndDate);
            double          shift      = swaptionVolatilities.shift(expiry, tenor);
            double          pvbp       = SwapPricer.LegPricer.pvbp(fixedLeg, ratesProvider);
            double          strike     = SwapPricer.LegPricer.couponEquivalent(fixedLeg, ratesProvider, pvbp);

            if (expiry < 0d)
            {     // Option has expired already
                return(PointSensitivityBuilder.none());
            }
            double      forward    = SwapPricer.parRate(underlying, ratesProvider);
            double      volatility = swaptionVolatilities.volatility(expiry, tenor, strike, forward);
            DoubleArray derivative = swaptionVolatilities.volatilityAdjoint(expiry, tenor, strike, forward).Derivatives;
            // Backward sweep
            double vega = Math.Abs(pvbp) * BlackFormulaRepository.vega(forward + shift, strike + shift, expiry, volatility) * swaption.LongShort.sign();
            // sensitivities
            Currency ccy = fixedLeg.Currency;
            SwaptionVolatilitiesName name = swaptionVolatilities.Name;

            return(PointSensitivityBuilder.of(SwaptionSabrSensitivity.of(name, expiry, tenor, ALPHA, ccy, vega * derivative.get(2)), SwaptionSabrSensitivity.of(name, expiry, tenor, BETA, ccy, vega * derivative.get(3)), SwaptionSabrSensitivity.of(name, expiry, tenor, RHO, ccy, vega * derivative.get(4)), SwaptionSabrSensitivity.of(name, expiry, tenor, NU, ccy, vega * derivative.get(5))));
        }
Ejemplo n.º 9
0
 private ResolvedCms(ResolvedCmsLeg cmsLeg, ResolvedSwapLeg payLeg)
 {
     JodaBeanUtils.notNull(cmsLeg, "cmsLeg");
     this.cmsLeg = cmsLeg;
     this.payLeg = payLeg;
     validate();
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Explain present value for a swap leg.
        /// </summary>
        /// <param name="leg">  the swap log </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the explain PV map </returns>
        public virtual ExplainMap explainPresentValue(ResolvedSwapLeg leg, RatesProvider provider)
        {
            ExplainMapBuilder builder = ExplainMap.builder();

            explainPresentValueInternal(leg, provider, builder);
            return(builder.build());
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity of the swaption to the rate curves.
        /// <para>
        /// The present value sensitivity is computed in a "sticky strike" style, i.e. the sensitivity to the
        /// curve nodes with the volatility at the swaption strike unchanged. This sensitivity does not include a potential
        /// change of volatility due to the implicit change of forward rate or moneyness.
        ///
        /// </para>
        /// </summary>
        /// <param name="swaption">  the swaption </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 presentValueSensitivityRatesStickyStrike(ResolvedSwaption swaption, RatesProvider ratesProvider, SwaptionVolatilities swaptionVolatilities)
        {
            validate(swaption, ratesProvider, swaptionVolatilities);
            double          expiry     = swaptionVolatilities.relativeTime(swaption.Expiry);
            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           volatility        = swaptionVolatilities.volatility(expiry, tenor, strike, forward);
            PutCall          putCall           = PutCall.ofPut(fixedLeg.PayReceive.Receive);
            double           price             = swaptionVolatilities.price(expiry, tenor, putCall, strike, forward, volatility);
            double           delta             = swaptionVolatilities.priceDelta(expiry, tenor, putCall, strike, forward, volatility);
            // Backward sweep
            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 + annuityCashDr * price)).combinedWith(discountSettleSensi.multipliedBy(sign * annuityCash * price)));
        }
Ejemplo n.º 12
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the future cash flows of the swap leg.
        /// <para>
        /// Each expected cash flow is added to the result.
        /// This is based on <seealso cref="#forecastValue(ResolvedSwapLeg, RatesProvider)"/>.
        ///
        /// </para>
        /// </summary>
        /// <param name="leg">  the swap leg for which the cash flows should be computed </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the cash flows </returns>
        public virtual CashFlows cashFlows(ResolvedSwapLeg leg, RatesProvider provider)
        {
            CashFlows cashFlowPeriods = cashFlowPeriodsInternal(leg, provider);
            CashFlows cashFlowEvents  = cashFlowEventsInternal(leg, provider);

            return(cashFlowPeriods.combinedWith(cashFlowEvents));
        }
        //-----------------------------------------------------------------------
        public virtual void floatingSwapLeg()
        {
            // a PeriodicSchedule generates a schedule of accrual periods
            // - interest is accrued every 6 months from 2014-02-12 to 2014-07-31
            // - accrual period dates are adjusted "modified following" using the "GBLO" holiday calendar
            // - there will be a long initial stub
            // - the regular accrual period dates will be at the end-of-month
            PeriodicSchedule accrualSchedule = PeriodicSchedule.builder().startDate(LocalDate.of(2014, 2, 12)).endDate(LocalDate.of(2016, 7, 31)).businessDayAdjustment(BusinessDayAdjustment.of(MODIFIED_FOLLOWING, HolidayCalendarIds.GBLO)).frequency(Frequency.P6M).stubConvention(StubConvention.LONG_INITIAL).rollConvention(RollConventions.EOM).build();
            // a PaymentSchedule generates a schedule of payment periods, based on the accrual schedule
            // - payments are every 6 months
            // - payments are 2 business days after the end of the period
            // - no compounding is needed as the payment schedule matches the accrual schedule
            PaymentSchedule paymentSchedule = PaymentSchedule.builder().paymentFrequency(Frequency.P6M).paymentRelativeTo(PaymentRelativeTo.PERIOD_END).paymentDateOffset(DaysAdjustment.ofBusinessDays(2, HolidayCalendarIds.GBLO)).build();
            // a NotionalSchedule generates a schedule of notional amounts, based on the payment schedule
            // - in this simple case the notional is 1 million GBP and does not change
            NotionalSchedule notionalSchedule = NotionalSchedule.of(Currency.GBP, 1_000_000);
            // a RateCalculationSwapLeg can represent a fixed or floating swap leg
            // - an IborRateCalculation is used to represent a floating Ibor rate
            // - the "Act/Act ISDA" day count is used
            // - the index is GBP LIBOR 6M
            // - fixing is 2 days before the start of the period using the "GBLO" holiday calendar
            RateCalculationSwapLeg swapLeg = RateCalculationSwapLeg.builder().payReceive(PayReceive.RECEIVE).accrualSchedule(accrualSchedule).paymentSchedule(paymentSchedule).notionalSchedule(notionalSchedule).calculation(IborRateCalculation.builder().dayCount(DayCounts.ACT_ACT_ISDA).index(IborIndices.GBP_LIBOR_6M).fixingRelativeTo(FixingRelativeTo.PERIOD_START).fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, HolidayCalendarIds.GBLO)).build()).build();
            // a ResolvedSwapLeg has all the dates of the cash flows
            // it remains valid so long as the holiday calendar does not change
            ResolvedSwapLeg resolvedLeg = swapLeg.resolve(ReferenceData.standard());

            Console.WriteLine("===== Floating =====");
            Console.WriteLine(JodaBeanSer.PRETTY.xmlWriter().write(swapLeg));
            Console.WriteLine();
            Console.WriteLine("===== Floating resolved =====");
            Console.WriteLine(JodaBeanSer.PRETTY.xmlWriter().write(resolvedLeg));
            Console.WriteLine();
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity of the swaption to the rate curves.
        /// <para>
        /// The present value sensitivity is computed in a "sticky strike" style, i.e. the sensitivity to the
        /// curve nodes with the volatility at the swaption strike unchanged. This sensitivity does not include a potential
        /// change of volatility due to the implicit change of forward rate or moneyness.
        ///
        /// </para>
        /// </summary>
        /// <param name="swaption">  the swaption </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 presentValueSensitivityRatesStickyStrike(ResolvedSwaption swaption, RatesProvider ratesProvider, SwaptionVolatilities swaptionVolatilities)
        {
            validate(swaption, ratesProvider, swaptionVolatilities);
            double          expiry     = swaptionVolatilities.relativeTime(swaption.Expiry);
            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);
            double  pvbp       = SwapPricer.LegPricer.pvbp(fixedLeg, ratesProvider);
            double  strike     = SwapPricer.LegPricer.couponEquivalent(fixedLeg, ratesProvider, pvbp);
            double  tenor      = swaptionVolatilities.tenor(fixedLeg.StartDate, fixedLeg.EndDate);
            double  volatility = swaptionVolatilities.volatility(expiry, tenor, strike, forward);
            PutCall putCall    = PutCall.ofPut(fixedLeg.PayReceive.Receive);
            double  price      = swaptionVolatilities.price(expiry, tenor, putCall, strike, forward, volatility);
            double  delta      = swaptionVolatilities.priceDelta(expiry, tenor, putCall, strike, forward, volatility);
            // Backward sweep
            PointSensitivityBuilder pvbpDr    = SwapPricer.LegPricer.pvbpSensitivity(fixedLeg, ratesProvider);
            PointSensitivityBuilder forwardDr = SwapPricer.parRateSensitivity(underlying, ratesProvider);
            double sign = swaption.LongShort.sign();

            return(pvbpDr.multipliedBy(price * sign * Math.Sign(pvbp)).combinedWith(forwardDr.multipliedBy(delta * Math.Abs(pvbp) * sign)));
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Computes cash flow equivalent of swap.
        /// <para>
        /// The swap should be a fix-for-Ibor swap without compounding, and its swap legs
        /// should not involve {@code PaymentEvent}.
        /// </para>
        /// <para>
        /// The return type is {@code ResolvedSwapLeg} in which individual payments are
        /// represented in terms of {@code NotionalExchange}.
        ///
        /// </para>
        /// </summary>
        /// <param name="swap">  the swap product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <returns> the cash flow equivalent </returns>
        public static ResolvedSwapLeg cashFlowEquivalentSwap(ResolvedSwap swap, RatesProvider ratesProvider)
        {
            validateSwap(swap);
            ResolvedSwapLeg cfFixed = cashFlowEquivalentFixedLeg(swap.getLegs(SwapLegType.FIXED).get(0), ratesProvider);
            ResolvedSwapLeg cfIbor  = cashFlowEquivalentIborLeg(swap.getLegs(SwapLegType.IBOR).get(0), ratesProvider);
            ResolvedSwapLeg leg     = ResolvedSwapLeg.builder().paymentEvents(Stream.concat(cfFixed.PaymentEvents.stream(), cfIbor.PaymentEvents.stream()).collect(Collectors.toList())).payReceive(PayReceive.RECEIVE).type(SwapLegType.OTHER).build();

            return(leg);
        }
Ejemplo n.º 16
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the Present Value of a Basis Point for a swap leg.
        /// <para>
        /// The Present Value of a Basis Point is the value of the leg when the rate is equal to 1.
        /// A better name would be "Present Value of 1".
        /// The quantity is also known as "physical annuity" or "level".
        /// </para>
        /// <para>
        /// Each period must not have FX reset or compounding.
        /// They must not be of type <seealso cref="KnownAmountSwapPaymentPeriod"/>.
        ///
        /// </para>
        /// </summary>
        /// <param name="leg">  the swap leg </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the Present Value of a Basis Point </returns>
        public virtual double pvbp(ResolvedSwapLeg leg, RatesProvider provider)
        {
            double pvbpLeg = 0d;

            foreach (SwapPaymentPeriod period in leg.PaymentPeriods)
            {
                pvbpLeg += paymentPeriodPricer.pvbp(period, provider);
            }
            return(pvbpLeg);
        }
Ejemplo n.º 17
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the Present Value of a Basis Point curve sensitivity for a fixed swap leg.
        /// <para>
        /// The Present Value of a Basis Point is the value of the leg when the rate is equal to 1.
        /// A better name would be "Present Value of 1".
        /// The quantity is also known as "physical annuity" or "level".
        /// </para>
        /// <para>
        /// Each period must not have FX reset or compounding.
        /// They must not be of type <seealso cref="KnownAmountSwapPaymentPeriod"/>.
        ///
        /// </para>
        /// </summary>
        /// <param name="fixedLeg">  the swap fixed leg </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the Present Value of a Basis Point sensitivity to the curves </returns>
        public virtual PointSensitivityBuilder pvbpSensitivity(ResolvedSwapLeg fixedLeg, RatesProvider provider)
        {
            PointSensitivityBuilder builder = PointSensitivityBuilder.none();

            foreach (SwapPaymentPeriod period in fixedLeg.PaymentPeriods)
            {
                builder = builder.combinedWith(paymentPeriodPricer.pvbpSensitivity(period, provider));
            }
            return(builder);
        }
Ejemplo n.º 18
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the accrued interest since the last payment.
        /// <para>
        /// This determines the payment period applicable at the valuation date and calculates
        /// the accrued interest since the last payment.
        /// The result is returned using the payment currency of the leg.
        ///
        /// </para>
        /// </summary>
        /// <param name="leg">  the leg </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the accrued interest of the swap leg </returns>
        public virtual CurrencyAmount accruedInterest(ResolvedSwapLeg leg, RatesProvider provider)
        {
            Optional <SwapPaymentPeriod> period = leg.findPaymentPeriod(provider.ValuationDate);

            if (period.Present)
            {
                double accruedInterest = paymentPeriodPricer.accruedInterest(period.get(), provider);
                return(CurrencyAmount.of(leg.Currency, accruedInterest));
            }
            return(CurrencyAmount.zero(leg.Currency));
        }
        /// <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);
        }
        //-------------------------------------------------------------------------
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @ImmutableConstructor private ResolvedIborCapFloor(ResolvedIborCapFloorLeg capFloorLeg, com.opengamma.strata.product.swap.ResolvedSwapLeg payLeg)
        private ResolvedIborCapFloor(ResolvedIborCapFloorLeg capFloorLeg, ResolvedSwapLeg payLeg)
        {
            JodaBeanUtils.notNull(capFloorLeg, "capFloorLeg");
            if (payLeg != null)
            {
                ArgChecker.isFalse(payLeg.PayReceive.Equals(capFloorLeg.PayReceive), "Legs must have different Pay/Receive flag, but both were {}", payLeg.PayReceive);
            }
            this.capFloorLeg = capFloorLeg;
            this.payLeg      = payLeg;
            this.currencies  = buildCurrencies(capFloorLeg, payLeg);
            this.indices     = buildIndices(capFloorLeg, payLeg);
        }
Ejemplo n.º 21
0
        // find the notional
        private CurrencyAmount buildLegNotional(ResolvedSwapLeg leg)
        {
            // check for NotionalPaymentPeriod
            SwapPaymentPeriod firstPaymentPeriod = leg.PaymentPeriods.get(0);

            if (firstPaymentPeriod is NotionalPaymentPeriod)
            {
                NotionalPaymentPeriod pp = (NotionalPaymentPeriod)firstPaymentPeriod;
                return(pp.NotionalAmount.positive());
            }
            return(NOT_FOUND);
        }
Ejemplo n.º 22
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)));
        }
Ejemplo n.º 23
0
        // calculates the present value of the events composing the leg in the currency of the swap leg
        internal virtual double presentValueEventsInternal(ResolvedSwapLeg leg, RatesProvider provider)
        {
            double total = 0d;

            foreach (SwapPaymentEvent @event in leg.PaymentEvents)
            {
                if ([email protected](provider.ValuationDate))
                {
                    total += paymentEventPricer.presentValue(@event, provider);
                }
            }
            return(total);
        }
Ejemplo n.º 24
0
        // calculates the present value of the periods composing the leg in the currency of the swap leg
        internal virtual double presentValuePeriodsInternal(ResolvedSwapLeg leg, RatesProvider provider)
        {
            double total = 0d;

            foreach (SwapPaymentPeriod period in leg.PaymentPeriods)
            {
                if (!period.PaymentDate.isBefore(provider.ValuationDate))
                {
                    total += paymentPeriodPricer.presentValue(period, provider);
                }
            }
            return(total);
        }
Ejemplo n.º 25
0
        private MultiCurrencyAmount currencyExposureEventsInternal(ResolvedSwapLeg leg, RatesProvider provider)
        {
            MultiCurrencyAmount total = MultiCurrencyAmount.empty();

            foreach (SwapPaymentEvent @event in leg.PaymentEvents)
            {
                if ([email protected](provider.ValuationDate))
                {
                    total = total.plus(paymentEventPricer.currencyExposure(@event, provider));
                }
            }
            return(total);
        }
Ejemplo n.º 26
0
        private double currentCashPeriodsInternal(ResolvedSwapLeg leg, RatesProvider provider)
        {
            double total = 0d;

            foreach (SwapPaymentPeriod period in leg.PaymentPeriods)
            {
                if (!period.PaymentDate.isBefore(provider.ValuationDate))
                {
                    total += paymentPeriodPricer.currentCash(period, provider);
                }
            }
            return(total);
        }
Ejemplo n.º 27
0
        private double currentCashEventsInternal(ResolvedSwapLeg leg, RatesProvider provider)
        {
            double total = 0d;

            foreach (SwapPaymentEvent @event in leg.PaymentEvents)
            {
                if ([email protected](provider.ValuationDate))
                {
                    total += paymentEventPricer.currentCash(@event, provider);
                }
            }
            return(total);
        }
Ejemplo n.º 28
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);
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the implied volatility of the swaption.
        /// </summary>
        /// <param name="swaption">  the swaption </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the volatilities </param>
        /// <returns> the implied volatility associated with the swaption </returns>
        public virtual double impliedVolatility(ResolvedSwaption swaption, RatesProvider ratesProvider, SwaptionVolatilities swaptionVolatilities)
        {
            validate(swaption, ratesProvider, swaptionVolatilities);
            double          expiry     = swaptionVolatilities.relativeTime(swaption.Expiry);
            ResolvedSwap    underlying = swaption.Underlying;
            ResolvedSwapLeg fixedLeg   = this.fixedLeg(underlying);

            ArgChecker.isTrue(expiry >= 0d, "Option must be before expiry to compute an implied volatility");
            double forward = SwapPricer.parRate(underlying, ratesProvider);
            double strike  = calculateStrike(fixedLeg);
            double tenor   = swaptionVolatilities.tenor(fixedLeg.StartDate, fixedLeg.EndDate);

            return(swaptionVolatilities.volatility(expiry, tenor, strike, forward));
        }
Ejemplo n.º 30
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);
        }