Esempio n. 1
0
        public virtual void present_value_delta_payer_receiver_parity()
        {
            CurrencyAmount pvDeltaLongPay  = PRICER_SWAPTION_BLACK.presentValueDelta(SWAPTION_LONG_PAY, MULTI_USD, BLACK_VOLS_USD_STD);
            CurrencyAmount pvDeltaShortRec = PRICER_SWAPTION_BLACK.presentValueDelta(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD);
            double         pvbp            = PRICER_SWAP.LegPricer.pvbp(RSWAP_PAY.getLegs(SwapLegType.FIXED).get(0), MULTI_USD);

            assertEquals(pvDeltaLongPay.Amount + pvDeltaShortRec.Amount, Math.Abs(pvbp), TOLERANCE_PV);
        }
Esempio n. 2
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);
        }
Esempio n. 3
0
        //-------------------------------------------------------------------------
        public virtual void present_value_formula()
        {
            double         forward    = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD);
            double         pvbp       = PRICER_SWAP.LegPricer.pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), MULTI_USD);
            double         volatility = BLACK_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.Expiry, SWAP_TENOR_YEAR, STRIKE, forward);
            double         expiry     = BLACK_VOLS_USD_STD.relativeTime(SWAPTION_LONG_REC.Expiry);
            double         pvExpected = Math.Abs(pvbp) * BlackFormulaRepository.price(forward, STRIKE, expiry, volatility, false);
            CurrencyAmount pvComputed = PRICER_SWAPTION_BLACK.presentValue(SWAPTION_LONG_REC, MULTI_USD, BLACK_VOLS_USD_STD);

            assertEquals(pvComputed.Currency, USD);
            assertEquals(pvComputed.Amount, pvExpected, TOLERANCE_PV);
        }
        //-------------------------------------------------------------------------
        public virtual void test_presentValue()
        {
            CurrencyAmount computedRec = SWAPTION_PRICER.presentValue(SWAPTION_REC_LONG, RATE_PROVIDER, VOLS);
            CurrencyAmount computedPay = SWAPTION_PRICER.presentValue(SWAPTION_PAY_SHORT, RATE_PROVIDER, VOLS);
            double         forward     = SWAP_PRICER.parRate(RSWAP_REC, RATE_PROVIDER);
            double         pvbp        = SWAP_PRICER.LegPricer.pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), RATE_PROVIDER);
            double         volatility  = VOLS.volatility(SWAPTION_REC_LONG.Expiry, TENOR_YEAR, RATE, forward);
            double         maturity    = VOLS.relativeTime(SWAPTION_REC_LONG.Expiry);
            double         expectedRec = pvbp * BlackFormulaRepository.price(forward + SwaptionSabrRateVolatilityDataSet.SHIFT, RATE + SwaptionSabrRateVolatilityDataSet.SHIFT, maturity, volatility, false);
            double         expectedPay = -pvbp *BlackFormulaRepository.price(forward + SwaptionSabrRateVolatilityDataSet.SHIFT, RATE + SwaptionSabrRateVolatilityDataSet.SHIFT, maturity, volatility, true);

            assertEquals(computedRec.Currency, USD);
            assertEquals(computedRec.Amount, expectedRec, NOTIONAL * TOL);
            assertEquals(computedPay.Currency, USD);
            assertEquals(computedPay.Amount, expectedPay, NOTIONAL * TOL);
        }
Esempio n. 5
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)));
        }
Esempio n. 6
0
        public virtual void test_presentValue_parity()
        {
            CurrencyAmount pvRecLong  = PRICER.presentValue(SWAPTION_REC_LONG, RATE_PROVIDER, VOLS);
            CurrencyAmount pvRecShort = PRICER.presentValue(SWAPTION_REC_SHORT, RATE_PROVIDER, VOLS);
            CurrencyAmount pvPayLong  = PRICER.presentValue(SWAPTION_PAY_LONG, RATE_PROVIDER, VOLS);
            CurrencyAmount pvPayShort = PRICER.presentValue(SWAPTION_PAY_SHORT, RATE_PROVIDER, VOLS);

            assertEquals(pvRecLong.Amount, -pvRecShort.Amount, NOTIONAL * TOL);
            assertEquals(pvPayLong.Amount, -pvPayShort.Amount, NOTIONAL * TOL);
            double forward     = SWAP_PRICER.parRate(RSWAP_REC, RATE_PROVIDER);
            double annuityCash = SWAP_PRICER.LegPricer.annuityCash(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), forward);
            double discount    = RATE_PROVIDER.discountFactor(EUR, SETTLE);
            double expected    = discount * annuityCash * (forward - RATE);

            assertEquals(pvPayLong.Amount - pvRecLong.Amount, expected, NOTIONAL * TOL);
            assertEquals(pvPayShort.Amount - pvRecShort.Amount, -expected, NOTIONAL * TOL);
        }
Esempio n. 7
0
        //-------------------------------------------------------------------------
        // checking that at least one leg is a fixed leg and returning the first one
        private ResolvedSwapLeg fixedLeg(ResolvedSwap swap)
        {
            IList <ResolvedSwapLeg> fixedLegs = swap.getLegs(SwapLegType.FIXED);

            if (fixedLegs.Count == 0)
            {
                throw new System.ArgumentException("Swap must contain a fixed leg");
            }
            return(fixedLegs[0]);
        }
        /// <summary>
        /// Checks that there is exactly one fixed leg and returns it.
        /// </summary>
        /// <param name="swap">  the swap </param>
        /// <returns> the fixed leg </returns>
        protected internal virtual ResolvedSwapLeg fixedLeg(ResolvedSwap swap)
        {
            ArgChecker.isFalse(swap.CrossCurrency, "Swap must be single currency");
            // find fixed leg
            IList <ResolvedSwapLeg> fixedLegs = swap.getLegs(SwapLegType.FIXED);

            if (fixedLegs.Count == 0)
            {
                throw new System.ArgumentException("Swap must contain a fixed leg");
            }
            return(fixedLegs[0]);
        }
Esempio n. 9
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity to piecewise constant volatility parameters of the Hull-White model.
        /// </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 Hull-White model parameter sensitivity of the swaption product </returns>
        public virtual DoubleArray presentValueSensitivityModelParamsHullWhite(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(DoubleArray.EMPTY);
            }
            ResolvedSwapLeg cashFlowEquiv = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap, ratesProvider);
            int             nPayments     = cashFlowEquiv.PaymentEvents.size();

            double[]   alpha              = new double[nPayments];
            double[][] alphaAdjoint       = new double[nPayments][];
            double[]   discountedCashFlow = new double[nPayments];
            for (int loopcf = 0; loopcf < nPayments; loopcf++)
            {
                NotionalExchange payment    = (NotionalExchange)cashFlowEquiv.PaymentEvents.get(loopcf);
                ValueDerivatives valueDeriv = hwProvider.alphaAdjoint(ratesProvider.ValuationDate, expiryDate, expiryDate, payment.PaymentDate);
                alpha[loopcf]              = valueDeriv.Value;
                alphaAdjoint[loopcf]       = valueDeriv.Derivatives.toArray();
                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);
            int    nParams = alphaAdjoint[0].Length;

            if (Math.Abs(kappa) > 1d / SMALL)
            {     // decays exponentially
                return(DoubleArray.filled(nParams));
            }
            double[] pvSensi = new double[nParams];
            double   sign    = (swaption.LongShort.Long ? 1d : -1d);

            for (int i = 0; i < nParams; ++i)
            {
                for (int loopcf = 0; loopcf < nPayments; loopcf++)
                {
                    pvSensi[i] += sign * discountedCashFlow[loopcf] * NORMAL.getPDF(omega * (kappa + alpha[loopcf])) * omega * alphaAdjoint[loopcf][i];
                }
            }
            return(DoubleArray.ofUnsafe(pvSensi));
        }
        //-------------------------------------------------------------------------
        public virtual void present_value_formula()
        {
            double                forward    = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD);
            double                pvbp       = PRICER_SWAP.LegPricer.pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), MULTI_USD);
            double                volatility = NORMAL_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.Expiry, SWAP_TENOR_YEAR, STRIKE, forward);
            NormalFunctionData    normalData = NormalFunctionData.of(forward, Math.Abs(pvbp), volatility);
            double                expiry     = NORMAL_VOLS_USD_STD.relativeTime(SWAPTION_LONG_REC.Expiry);
            EuropeanVanillaOption option     = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT);
            double                pvExpected = NORMAL.getPriceFunction(option).apply(normalData);
            CurrencyAmount        pvComputed = PRICER_SWAPTION_NORMAL.presentValue(SWAPTION_LONG_REC, MULTI_USD, NORMAL_VOLS_USD_STD);

            assertEquals(pvComputed.Currency, USD);
            assertEquals(pvComputed.Amount, pvExpected, TOLERANCE_PV);
        }
        //-------------------------------------------------------------------------
        public virtual void test_presentValue()
        {
            CurrencyAmount        pvRecComputed = PRICER_SWAPTION.presentValue(SWAPTION_REC_LONG, RATE_PROVIDER, VOLS);
            CurrencyAmount        pvPayComputed = PRICER_SWAPTION.presentValue(SWAPTION_PAY_SHORT, RATE_PROVIDER, VOLS);
            double                forward       = PRICER_SWAP.parRate(RSWAP_REC, RATE_PROVIDER);
            double                annuityCash   = PRICER_SWAP.LegPricer.annuityCash(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), forward);
            double                volatility    = VOLS.volatility(SWAPTION_REC_LONG.Expiry, SWAP_TENOR_YEAR, STRIKE, forward);
            double                discount      = RATE_PROVIDER.discountFactor(USD, SETTLE_DATE);
            NormalFunctionData    normalData    = NormalFunctionData.of(forward, annuityCash * discount, volatility);
            double                expiry        = VOLS.relativeTime(SWAPTION_REC_LONG.Expiry);
            EuropeanVanillaOption optionRec     = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT);
            EuropeanVanillaOption optionPay     = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.CALL);
            double                pvRecExpected = NORMAL.getPriceFunction(optionRec).apply(normalData);
            double                pvPayExpected = -NORMAL.getPriceFunction(optionPay).apply(normalData);

            assertEquals(pvRecComputed.Currency, USD);
            assertEquals(pvRecComputed.Amount, pvRecExpected, NOTIONAL * TOL);
            assertEquals(pvPayComputed.Currency, USD);
            assertEquals(pvPayComputed.Amount, pvPayExpected, NOTIONAL * TOL);
        }
Esempio n. 12
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity of the swaption product.
        /// <para>
        /// The present value sensitivity of the product is the sensitivity of the present value to
        /// the underlying curves.
        ///
        /// </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 point sensitivity to the rate curves </returns>
        public virtual PointSensitivityBuilder presentValueSensitivityRates(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(PointSensitivityBuilder.none());
            }
            ImmutableMap <Payment, PointSensitivityBuilder> cashFlowEquivSensi = CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivitySwap(swap, ratesProvider);
            ImmutableList <Payment> list = cashFlowEquivSensi.Keys.asList();
            ImmutableList <PointSensitivityBuilder> listSensi = cashFlowEquivSensi.values().asList();
            int nPayments = list.size();

            double[] alpha = new double[nPayments];
            double[] discountedCashFlow = new double[nPayments];
            for (int loopcf = 0; loopcf < nPayments; loopcf++)
            {
                Payment payment = list.get(loopcf);
                alpha[loopcf] = hwProvider.alpha(ratesProvider.ValuationDate, expiryDate, expiryDate, payment.Date);
                discountedCashFlow[loopcf] = paymentPricer.presentValueAmount(payment, ratesProvider);
            }
            double omega = (swap.getLegs(SwapLegType.FIXED).get(0).PayReceive.Pay ? -1d : 1d);
            double kappa = computeKappa(hwProvider, discountedCashFlow, alpha, omega);
            PointSensitivityBuilder point = PointSensitivityBuilder.none();

            for (int loopcf = 0; loopcf < nPayments; loopcf++)
            {
                Payment payment = list.get(loopcf);
                double  cdf     = NORMAL.getCDF(omega * (kappa + alpha[loopcf]));
                point = point.combinedWith(paymentPricer.presentValueSensitivity(payment, ratesProvider).multipliedBy(cdf));
                if (!listSensi.get(loopcf).Equals(PointSensitivityBuilder.none()))
                {
                    point = point.combinedWith(listSensi.get(loopcf).multipliedBy(cdf * ratesProvider.discountFactor(payment.Currency, payment.Date)));
                }
            }
            return(swaption.LongShort.Long ? point : point.multipliedBy(-1d));
        }
Esempio n. 13
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;
            }
Esempio n. 14
0
 //-------------------------------------------------------------------------
 private static void validateSwap(ResolvedSwap swap)
 {
     ArgChecker.isTrue(swap.Legs.size() == 2, "swap should have 2 legs");
     ArgChecker.isTrue(swap.getLegs(SwapLegType.FIXED).size() == 1, "swap should have unique fixed leg");
     ArgChecker.isTrue(swap.getLegs(SwapLegType.IBOR).size() == 1, "swap should have unique Ibor leg");
 }
Esempio n. 15
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes cash flow equivalent and sensitivity 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 a map of {@code NotionalExchange} and {@code PointSensitivityBuilder}.
        ///
        /// </para>
        /// </summary>
        /// <param name="swap">  the swap product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <returns> the cash flow equivalent and sensitivity </returns>
        public static ImmutableMap <Payment, PointSensitivityBuilder> cashFlowEquivalentAndSensitivitySwap(ResolvedSwap swap, RatesProvider ratesProvider)
        {
            validateSwap(swap);
            ImmutableMap <Payment, PointSensitivityBuilder> mapFixed = cashFlowEquivalentAndSensitivityFixedLeg(swap.getLegs(SwapLegType.FIXED).get(0), ratesProvider);
            ImmutableMap <Payment, PointSensitivityBuilder> mapIbor  = cashFlowEquivalentAndSensitivityIborLeg(swap.getLegs(SwapLegType.IBOR).get(0), ratesProvider);

            return(ImmutableMap.builder <Payment, PointSensitivityBuilder>().putAll(mapFixed).putAll(mapIbor).build());
        }
        //-------------------------------------------------------------------------
        /// <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));
        }