Example #1
0
        public List <CashFlow> expectedCashflows()
        {
            calcBondFactor();

            List <CashFlow> expectedcashflows = new List <CashFlow>();

            List <double> notionals = new InitializedList <double>(schedule_.Count);

            notionals[0] = notionals_[0];
            for (int i = 0; i < schedule_.Count - 1; ++i)
            {
                double currentNotional = notionals[i];
                double smm             = SMM(schedule_[i]);
                double prepay          = (notionals[i] * bondFactors_[i + 1]) / bondFactors_[i] * smm;
                double actualamort     = currentNotional * (1 - bondFactors_[i + 1] / bondFactors_[i]);
                notionals[i + 1] = currentNotional - actualamort - prepay;

                // ADD
                CashFlow c1 = new VoluntaryPrepay(prepay, schedule_[i + 1]);
                CashFlow c2 = new AmortizingPayment(actualamort, schedule_[i + 1]);
                CashFlow c3 = new FixedRateCoupon(schedule_[i + 1], currentNotional, new InterestRate(PassThroughRate_, dCounter_, Compounding.Simple, Frequency.Annual), schedule_[i], schedule_[i + 1]);
                expectedcashflows.Add(c1);
                expectedcashflows.Add(c2);
                expectedcashflows.Add(c3);
            }
            notionals[notionals.Count - 1] = 0.0;

            return(expectedcashflows);
        }
Example #2
0
        public override void setupArguments(IPricingEngineArguments args)
        {
            base.setupArguments(args);

            VanillaSwap.Arguments arguments = args as VanillaSwap.Arguments;
            if (arguments == null) // it's a swap engine...
            {
                return;
            }

            arguments.type    = type_;
            arguments.nominal = nominal_;

            List <CashFlow> fixedCoupons = fixedLeg();

            arguments.fixedResetDates = new InitializedList <Date>(fixedCoupons.Count);
            arguments.fixedPayDates   = new InitializedList <Date>(fixedCoupons.Count);
            arguments.fixedCoupons    = new InitializedList <double>(fixedCoupons.Count);

            for (int i = 0; i < fixedCoupons.Count; ++i)
            {
                FixedRateCoupon coupon = (FixedRateCoupon)fixedCoupons[i];

                arguments.fixedPayDates[i]   = coupon.date();
                arguments.fixedResetDates[i] = coupon.accrualStartDate();
                arguments.fixedCoupons[i]    = coupon.amount();
            }

            List <CashFlow> floatingCoupons = floatingLeg();

            arguments.floatingResetDates   = new InitializedList <Date>(floatingCoupons.Count);
            arguments.floatingPayDates     = new InitializedList <Date>(floatingCoupons.Count);
            arguments.floatingFixingDates  = new InitializedList <Date>(floatingCoupons.Count);
            arguments.floatingAccrualTimes = new InitializedList <double>(floatingCoupons.Count);
            arguments.floatingSpreads      = new InitializedList <double>(floatingCoupons.Count);
            arguments.floatingCoupons      = new InitializedList <double>(floatingCoupons.Count);
            for (int i = 0; i < floatingCoupons.Count; ++i)
            {
                IborCoupon coupon = (IborCoupon)floatingCoupons[i];

                arguments.floatingResetDates[i] = coupon.accrualStartDate();
                arguments.floatingPayDates[i]   = coupon.date();

                arguments.floatingFixingDates[i]  = coupon.fixingDate();
                arguments.floatingAccrualTimes[i] = coupon.accrualPeriod();
                arguments.floatingSpreads[i]      = coupon.spread();
                try
                {
                    arguments.floatingCoupons[i] = coupon.amount();
                }
                catch
                {
                    arguments.floatingCoupons[i] = default(double);
                }
            }
        }
Example #3
0
        public double AmortizationValue(Date d)
        {
            // Check Date
            if (d < _tradeDate || d > _maturityDate)
            {
                return(0);
            }

            double totAmortized = 0;
            Date   lastDate     = _tradeDate;

            foreach (CashFlow c in cashflows_)
            {
                if (c.date() <= d)
                {
                    lastDate = c.date();
                    if (c is QLCore.AmortizingPayment)
                    {
                        totAmortized += (c as QLCore.AmortizingPayment).amount();
                    }
                }
                else
                {
                    break;
                }
            }


            if (lastDate < d)
            {
                // lastDate < d let calculate last interest

                // Base Interest
                InterestRate    r1           = new InterestRate(_couponRate, _dCounter, Compounding.Simple, _payFrequency);
                FixedRateCoupon c1           = new FixedRateCoupon(d, _faceValue, r1, lastDate, d);
                double          baseInterest = c1.amount();

                //
                InterestRate    r2            = new InterestRate(_yield, _dCounter, Compounding.Simple, _payFrequency);
                FixedRateCoupon c2            = new FixedRateCoupon(d, _marketValue, r2, lastDate, d);
                double          yieldInterest = c2.amount();

                totAmortized += Math.Abs(baseInterest - yieldInterest);
            }


            if (_isPremium)
            {
                return(_marketValue - totAmortized);
            }
            else
            {
                return(_marketValue + totAmortized);
            }
        }
        /// <summary>
        /// CDS quoted as running-spread only
        /// </summary>
        /// <param name="side">Whether the protection is bought or sold.</param>
        /// <param name="notional">Notional value</param>
        /// <param name="spread">Running spread in fractional units.</param>
        /// <param name="schedule">Coupon schedule.</param>
        /// <param name="convention">Business-day convention for payment-date adjustment.</param>
        /// <param name="dayCounter">Day-count convention for accrual.</param>
        /// <param name="settlesAccrual">Whether or not the accrued coupon is due in the event of a default.</param>
        /// <param name="paysAtDefaultTime">If set to true, any payments triggered by a default event are
        /// due at default time. If set to false, they are due at the end of the accrual period.</param>
        /// <param name="protectionStart">The first date where a default event will trigger the contract.</param>
        /// <param name="claim"></param>
        /// <param name="lastPeriodDayCounter">Day-count convention for accrual in last period</param>
        /// <param name="rebatesAccrual">The protection seller pays the accrued scheduled current coupon at the start
        /// of the contract. The rebate date is not provided but computed to be two days after protection start.</param>
        public CreditDefaultSwap(Protection.Side side,
                                 double notional,
                                 double spread,
                                 Schedule schedule,
                                 BusinessDayConvention convention,
                                 DayCounter dayCounter,
                                 bool settlesAccrual             = true,
                                 bool paysAtDefaultTime          = true,
                                 Date protectionStart            = null,
                                 Claim claim                     = null,
                                 DayCounter lastPeriodDayCounter = null,
                                 bool rebatesAccrual             = true)
        {
            side_              = side;
            notional_          = notional;
            upfront_           = null;
            runningSpread_     = spread;
            settlesAccrual_    = settlesAccrual;
            paysAtDefaultTime_ = paysAtDefaultTime;
            claim_             = claim;
            protectionStart_   = protectionStart ?? schedule[0];

            Utils.QL_REQUIRE(protectionStart_ <= schedule[0] ||
                             schedule.rule() == DateGeneration.Rule.CDS ||
                             schedule.rule() == DateGeneration.Rule.CDS2015
                             , () => "protection can not start after accrual");

            leg_ = new FixedRateLeg(schedule)
                   .withLastPeriodDayCounter(lastPeriodDayCounter)
                   .withCouponRates(spread, dayCounter)
                   .withNotionals(notional)
                   .withPaymentAdjustment(convention);

            Date effectiveUpfrontDate = schedule.calendar().advance(protectionStart_, 2, TimeUnit.Days, convention);

            // '2' is used above since the protection start is assumed to be on trade_date + 1
            if (rebatesAccrual)
            {
                FixedRateCoupon firstCoupon = leg_[0] as FixedRateCoupon;

                Date rebateDate = effectiveUpfrontDate;
                accrualRebate_ = new SimpleCashFlow(firstCoupon.accruedAmount(protectionStart_), rebateDate);
            }

            upfrontPayment_ = new SimpleCashFlow(0.0, effectiveUpfrontDate);

            if (claim_ == null)
            {
                claim_ = new FaceValueClaim();
            }

            claim_.registerWith(update);
            maturity_ = schedule.dates().Last();
        }
        // other
        public override void setupArguments(IPricingEngineArguments args)
        {
            base.setupArguments(args);

            YearOnYearInflationSwap.Arguments arguments = args as YearOnYearInflationSwap.Arguments;

            if (arguments == null) // it's a swap engine...
            {
                return;
            }

            arguments.type    = type_;
            arguments.nominal = nominal_;

            List <CashFlow> fixedCoupons = fixedLeg();

            arguments.fixedResetDates = arguments.fixedPayDates = new List <Date>(fixedCoupons.Count);
            arguments.fixedCoupons    = new List <double>(fixedCoupons.Count);

            for (int i = 0; i < fixedCoupons.Count; ++i)
            {
                FixedRateCoupon coupon = fixedCoupons[i] as FixedRateCoupon;

                arguments.fixedPayDates.Add(coupon.date());
                arguments.fixedResetDates.Add(coupon.accrualStartDate());
                arguments.fixedCoupons.Add(coupon.amount());
            }

            List <CashFlow> yoyCoupons = yoyLeg();

            arguments.yoyResetDates   = arguments.yoyPayDates = arguments.yoyFixingDates = new List <Date>(yoyCoupons.Count);
            arguments.yoyAccrualTimes = new List <double>(yoyCoupons.Count);
            arguments.yoySpreads      = new List <double>(yoyCoupons.Count);
            arguments.yoyCoupons      = new List <double?>(yoyCoupons.Count);
            for (int i = 0; i < yoyCoupons.Count; ++i)
            {
                YoYInflationCoupon coupon = yoyCoupons[i] as YoYInflationCoupon;

                arguments.yoyResetDates.Add(coupon.accrualStartDate());
                arguments.yoyPayDates.Add(coupon.date());

                arguments.yoyFixingDates.Add(coupon.fixingDate());
                arguments.yoyAccrualTimes.Add(coupon.accrualPeriod());
                arguments.yoySpreads.Add(coupon.spread());
                try
                {
                    arguments.yoyCoupons.Add(coupon.amount());
                }
                catch (Exception)
                {
                    arguments.yoyCoupons.Add(null);
                }
            }
        }
Example #6
0
        void addEffectiveInterestRateAmortizing()
        {
            // Amortizing Schedule
            Schedule schedule = new Schedule(_tradeDate, _maturityDate, new Period(_payFrequency),
                                             _calendar, BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted,
                                             DateGeneration.Rule.Backward, false);
            double currentNominal = _marketValue;
            Date   prevDate       = _tradeDate;
            Date   actualDate     = _tradeDate;

            for (int i = 1; i < schedule.Count; ++i)
            {
                actualDate = schedule[i];
                InterestRate    rate = new InterestRate(_yield, _dCounter, Compounding.Simple, Frequency.Annual);
                InterestRate    rate2 = new InterestRate(_couponRate, _dCounter, Compounding.Simple, Frequency.Annual);
                FixedRateCoupon r, r2;
                if (i > 1)
                {
                    r  = new FixedRateCoupon(actualDate, currentNominal, rate, prevDate, actualDate, prevDate, actualDate);
                    r2 = new FixedRateCoupon(actualDate, currentNominal, rate2, prevDate, actualDate, prevDate, actualDate, null, _originalPayment);
                }

                else
                {
                    Calendar nullCalendar = new NullCalendar();
                    Period   p1           = new Period(_payFrequency);
                    Date     testDate     = nullCalendar.advance(actualDate, -1 * p1);

                    r  = new FixedRateCoupon(actualDate, currentNominal, rate, testDate, actualDate, prevDate, actualDate);
                    r2 = new FixedRateCoupon(actualDate, currentNominal, rate2, testDate, actualDate, prevDate, actualDate, null, _originalPayment);
                }

                double amort = Math.Round(Math.Abs(_originalPayment - r.amount()), 2);

                AmortizingPayment p = new AmortizingPayment(amort, actualDate);
                if (_isPremium)
                {
                    currentNominal -= Math.Abs(amort);
                }
                else
                {
                    currentNominal += Math.Abs(amort);
                }


                cashflows_.Add(r2);
                cashflows_.Add(p);
                prevDate = actualDate;
            }

            // Add single redemption for yield calculation
            setSingleRedemption(_faceValue, 100, _maturityDate);
        }
Example #7
0
        // other
        public override void setupArguments(IPricingEngineArguments args)
        {
            base.setupArguments(args);

            AssetSwap.Arguments arguments = args as AssetSwap.Arguments;

            if (arguments == null) // it's a swap engine...
            {
                return;
            }

            List <CashFlow> fixedCoupons = bondLeg();

            arguments.fixedResetDates = arguments.fixedPayDates = new List <Date>(fixedCoupons.Count);
            arguments.fixedCoupons    = new List <double>(fixedCoupons.Count);

            for (int i = 0; i < fixedCoupons.Count; ++i)
            {
                FixedRateCoupon coupon = fixedCoupons[i] as FixedRateCoupon;

                arguments.fixedPayDates[i]   = coupon.date();
                arguments.fixedResetDates[i] = coupon.accrualStartDate();
                arguments.fixedCoupons[i]    = coupon.amount();
            }

            List <CashFlow> floatingCoupons = floatingLeg();

            arguments.floatingResetDates      = arguments.floatingPayDates =
                arguments.floatingFixingDates = new List <Date>(floatingCoupons.Count);
            arguments.floatingAccrualTimes    = new List <double>(floatingCoupons.Count);
            arguments.floatingSpreads         = new List <double>(floatingCoupons.Count);

            for (int i = 0; i < floatingCoupons.Count; ++i)
            {
                FloatingRateCoupon coupon = floatingCoupons[i] as FloatingRateCoupon;

                arguments.floatingResetDates[i]   = coupon.accrualStartDate();
                arguments.floatingPayDates[i]     = coupon.date();
                arguments.floatingFixingDates[i]  = coupon.fixingDate();
                arguments.floatingAccrualTimes[i] = coupon.accrualPeriod();
                arguments.floatingSpreads[i]      = coupon.spread();
            }
        }
        /// <summary>
        /// CDS quoted as upfront and running spread
        /// </summary>
        /// <param name="side">Whether the protection is bought or sold.</param>
        /// <param name="notional"> Notional value</param>
        /// <param name="upfront">Upfront in fractional units.</param>
        /// <param name="runningSpread">Running spread in fractional units.</param>
        /// <param name="schedule">Coupon schedule.</param>
        /// <param name="convention">Business-day convention for payment-date adjustment.</param>
        /// <param name="dayCounter">Day-count convention for accrual.</param>
        /// <param name="settlesAccrual">Whether or not the accrued coupon is due in the event of a default.</param>
        /// <param name="paysAtDefaultTime">If set to true, any payments triggered by a default event are
        /// due at default time. If set to false, they are due at the end of the accrual period.</param>
        /// <param name="protectionStart">The first date where a default event will trigger the contract.</param>
        /// <param name="upfrontDate">Settlement date for the upfront payment.</param>
        /// <param name="claim"></param>
        /// <param name="lastPeriodDayCounter">Day-count convention for accrual in last period</param>
        /// <param name="rebatesAccrual">The protection seller pays the accrued scheduled current coupon at the start
        /// of the contract. The rebate date is not provided but computed to be two days after protection start.</param>
        public CreditDefaultSwap(Protection.Side side,
                                 double notional,
                                 double upfront,
                                 double runningSpread,
                                 Schedule schedule,
                                 BusinessDayConvention convention,
                                 DayCounter dayCounter,
                                 bool settlesAccrual             = true,
                                 bool paysAtDefaultTime          = true,
                                 Date protectionStart            = null,
                                 Date upfrontDate                = null,
                                 Claim claim                     = null,
                                 DayCounter lastPeriodDayCounter = null,
                                 bool rebatesAccrual             = true)
        {
            side_              = side;
            notional_          = notional;
            upfront_           = upfront;
            runningSpread_     = runningSpread;
            settlesAccrual_    = settlesAccrual;
            paysAtDefaultTime_ = paysAtDefaultTime;
            claim_             = claim;
            protectionStart_   = protectionStart ?? schedule[0];

            Utils.QL_REQUIRE(protectionStart_ <= schedule[0] ||
                             schedule.rule() == DateGeneration.Rule.CDS
                             , () => "protection can not start after accrual");
            leg_ = new FixedRateLeg(schedule)
                   .withLastPeriodDayCounter(lastPeriodDayCounter)
                   .withCouponRates(runningSpread, dayCounter)
                   .withNotionals(notional)
                   .withPaymentAdjustment(convention);

            // If empty, adjust to T+3 standard settlement, alternatively add
            //  an arbitrary date to the constructor
            Date effectiveUpfrontDate = upfrontDate == null?
                                        schedule.calendar().advance(protectionStart_, 2, TimeUnit.Days, convention) : upfrontDate;

            // '2' is used above since the protection start is assumed to be
            //   on trade_date + 1
            upfrontPayment_ = new SimpleCashFlow(notional * upfront, effectiveUpfrontDate);
            Utils.QL_REQUIRE(effectiveUpfrontDate >= protectionStart_, () => "upfront can not be due before contract start");

            if (rebatesAccrual)
            {
                FixedRateCoupon firstCoupon = leg_[0] as FixedRateCoupon;
                // adjust to T+3 standard settlement, alternatively add
                //  an arbitrary date to the constructor

                Date rebateDate = effectiveUpfrontDate;

                accrualRebate_ = new SimpleCashFlow(firstCoupon.accruedAmount(protectionStart_), rebateDate);
            }

            if (claim_ == null)
            {
                claim_ = new FaceValueClaim();
            }
            claim_.registerWith(update);

            maturity_ = schedule.dates().Last();
        }
        public override void calculate()
        {
            Date exerciseDate = arguments_.exercise.date(0);

            // the part of the swap preceding exerciseDate should be truncated
            // to avoid taking into account unwanted cashflows
            // for the moment we add a check avoiding this situation
            VanillaSwap swap = arguments_.swap;

            double          strike      = swap.fixedRate;
            List <CashFlow> fixedLeg    = swap.fixedLeg();
            FixedRateCoupon firstCoupon = fixedLeg[0] as FixedRateCoupon;

            Utils.QL_REQUIRE(firstCoupon != null, () => "wrong coupon type");

            Utils.QL_REQUIRE(firstCoupon.accrualStartDate() >= exerciseDate,
                             () => "swap start (" + firstCoupon.accrualStartDate() + ") before exercise date ("
                             + exerciseDate + ") not supported in Black swaption engine");

            // using the forecasting curve
            swap.setPricingEngine(new DiscountingSwapEngine(swap.iborIndex().forwardingTermStructure()));
            double atmForward = swap.fairRate();

            // Volatilities are quoted for zero-spreaded swaps.
            // Therefore, any spread on the floating leg must be removed
            // with a corresponding correction on the fixed leg.
            if (swap.spread.IsNotEqual(0.0))
            {
                double correction = swap.spread * Math.Abs(swap.floatingLegBPS() / swap.fixedLegBPS());
                strike     -= correction;
                atmForward -= correction;
                results_.additionalResults["spreadCorrection"] = correction;
            }
            else
            {
                results_.additionalResults["spreadCorrection"] = 0.0;
            }
            results_.additionalResults["strike"]     = strike;
            results_.additionalResults["atmForward"] = atmForward;

            // using the discounting curve
            swap.setPricingEngine(new DiscountingSwapEngine(discountCurve_, false));
            double annuity = 0;

            if (arguments_.settlementType == Settlement.Type.Physical ||
                (arguments_.settlementType == Settlement.Type.Cash &&
                 arguments_.settlementMethod == Settlement.Method.CollateralizedCashPrice))
            {
                annuity = Math.Abs(swap.fixedLegBPS()) / Const.BASIS_POINT;
            }
            else if (arguments_.settlementType == Settlement.Type.Cash &&
                     arguments_.settlementMethod == Settlement.Method.ParYieldCurve)
            {
                DayCounter dayCount = firstCoupon.dayCounter();

                // we assume that the cash settlement date is equal
                // to the swap start date
                Date discountDate = model_ == CashAnnuityModel.DiscountCurve
                                ? firstCoupon.accrualStartDate()
                                : discountCurve_.link.referenceDate();

                double fixedLegCashBPS =
                    CashFlows.bps(fixedLeg,
                                  new InterestRate(atmForward, dayCount, Compounding.Compounded, Frequency.Annual), false,
                                  discountDate);

                annuity = Math.Abs(fixedLegCashBPS / Const.BASIS_POINT) * discountCurve_.link.discount(discountDate);
            }
            else
            {
                Utils.QL_FAIL("unknown settlement type");
            }
            results_.additionalResults["annuity"] = annuity;

            double swapLength = vol_.link.swapLength(swap.floatingSchedule().dates().First(),
                                                     swap.floatingSchedule().dates().Last());

            results_.additionalResults["swapLength"] = swapLength;

            double variance = vol_.link.blackVariance(exerciseDate,
                                                      swapLength,
                                                      strike);
            double displacement = displacement_ == null
                               ? vol_.link.shift(exerciseDate, swapLength)
                               : Convert.ToDouble(displacement_);

            double stdDev = Math.Sqrt(variance);

            results_.additionalResults["stdDev"] = stdDev;
            Option.Type w = (arguments_.type == VanillaSwap.Type.Payer) ? Option.Type.Call : Option.Type.Put;
            results_.value = new Spec().value(w, strike, atmForward, stdDev, annuity, displacement);

            double exerciseTime = vol_.link.timeFromReference(exerciseDate);

            results_.additionalResults["vega"] =
                new Spec().vega(strike, atmForward, stdDev, exerciseTime, annuity, displacement);
        }
Example #10
0
        public override void calculate()
        {
            Utils.QL_REQUIRE(numericalFix_ == NumericalFix.None || numericalFix_ == NumericalFix.Taylor, () =>
                             "numerical fix must be None or Taylor");
            Utils.QL_REQUIRE(accrualBias_ == AccrualBias.HalfDayBias || accrualBias_ == AccrualBias.NoBias, () =>
                             "accrual bias must be HalfDayBias or NoBias");
            Utils.QL_REQUIRE(forwardsInCouponPeriod_ == ForwardsInCouponPeriod.Flat ||
                             forwardsInCouponPeriod_ == ForwardsInCouponPeriod.Piecewise, () =>
                             "forwards in coupon period must be Flat or Piecewise");

            // it would be possible to handle the cases which are excluded below,
            // but the ISDA engine is not explicitly specified to handle them,
            // so we just forbid them too

            Actual365Fixed dc  = new Actual365Fixed();
            Actual360      dc1 = new Actual360();
            Actual360      dc2 = new Actual360(true);

            Date evalDate = Settings.Instance.evaluationDate();

            // check if given curves are ISDA compatible
            // (the interpolation is checked below)

            Utils.QL_REQUIRE(!discountCurve_.empty(), () => "no discount term structure set");
            Utils.QL_REQUIRE(!probability_.empty(), () => "no probability term structure set");
            Utils.QL_REQUIRE(discountCurve_.link.dayCounter() == dc, () =>
                             "yield term structure day counter (" + discountCurve_.link.dayCounter() + ") should be Act/365(Fixed)");
            Utils.QL_REQUIRE(probability_.link.dayCounter() == dc, () =>
                             "probability term structure day counter (" + probability_.link.dayCounter() + ") should be "
                             + "Act/365(Fixed)");
            Utils.QL_REQUIRE(discountCurve_.link.referenceDate() == evalDate, () =>
                             "yield term structure reference date (" + discountCurve_.link.referenceDate()
                             + " should be evaluation date (" + evalDate + ")");
            Utils.QL_REQUIRE(probability_.link.referenceDate() == evalDate, () =>
                             "probability term structure reference date (" + probability_.link.referenceDate()
                             + " should be evaluation date (" + evalDate + ")");
            Utils.QL_REQUIRE(arguments_.settlesAccrual, () => "ISDA engine not compatible with non accrual paying CDS");
            Utils.QL_REQUIRE(arguments_.paysAtDefaultTime, () => "ISDA engine not compatible with end period payment");
            Utils.QL_REQUIRE((arguments_.claim as FaceValueClaim) != null, () =>
                             "ISDA engine not compatible with non face value claim");

            Date maturity = arguments_.maturity;
            Date effectiveProtectionStart = Date.Max(arguments_.protectionStart, evalDate + 1);

            // collect nodes from both curves and sort them
            List <Date> yDates = new List <Date>(), cDates = new List <Date>();

            var castY1 = discountCurve_.link as PiecewiseYieldCurve <Discount, LogLinear>;
            var castY2 = discountCurve_.link as InterpolatedForwardCurve <BackwardFlat>;
            var castY3 = discountCurve_.link as InterpolatedForwardCurve <ForwardFlat>;
            var castY4 = discountCurve_.link as FlatForward;

            if (castY1 != null)
            {
                if (castY1.dates() != null)
                {
                    yDates = castY1.dates();
                }
            }
            else if (castY2 != null)
            {
                yDates = castY2.dates();
            }
            else if (castY3 != null)
            {
                yDates = castY3.dates();
            }
            else if (castY4 != null)
            {
            }
            else
            {
                Utils.QL_FAIL("Yield curve must be flat forward interpolated");
            }

            var castC1 = probability_.link as InterpolatedSurvivalProbabilityCurve <LogLinear>;
            var castC2 = probability_.link as InterpolatedHazardRateCurve <BackwardFlat>;
            var castC3 = probability_.link as FlatHazardRate;

            if (castC1 != null)
            {
                cDates = castC1.dates();
            }
            else if (castC2 != null)
            {
                cDates = castC2.dates();
            }
            else if (castC3 != null)
            {
            }
            else
            {
                Utils.QL_FAIL("Credit curve must be flat forward interpolated");
            }

            // Todo check
            List <Date> nodes = yDates.Union(cDates).ToList();

            if (nodes.empty())
            {
                nodes.Add(maturity);
            }
            double nFix = (numericalFix_ == NumericalFix.None ? 1E-50 : 0.0);

            // protection leg pricing (npv is always negative at this stage)
            double protectionNpv = 0.0;

            Date   d0 = effectiveProtectionStart - 1;
            double P0 = discountCurve_.link.discount(d0);
            double Q0 = probability_.link.survivalProbability(d0);
            Date   d1;
            int    result = nodes.FindIndex(item => item > effectiveProtectionStart);

            for (int it = result; it < nodes.Count; ++it)
            {
                if (nodes[it] > maturity)
                {
                    d1 = maturity;
                    it = nodes.Count - 1; //early exit
                }
                else
                {
                    d1 = nodes[it];
                }
                double P1 = discountCurve_.link.discount(d1);
                double Q1 = probability_.link.survivalProbability(d1);

                double fhat  = Math.Log(P0) - Math.Log(P1);
                double hhat  = Math.Log(Q0) - Math.Log(Q1);
                double fhphh = fhat + hhat;

                if (fhphh < 1E-4 && numericalFix_ == NumericalFix.Taylor)
                {
                    double fhphhq = fhphh * fhphh;
                    protectionNpv +=
                        P0 * Q0 * hhat * (1.0 - 0.5 * fhphh + 1.0 / 6.0 * fhphhq -
                                          1.0 / 24.0 * fhphhq * fhphh +
                                          1.0 / 120 * fhphhq * fhphhq);
                }
                else
                {
                    protectionNpv += hhat / (fhphh + nFix) * (P0 * Q0 - P1 * Q1);
                }
                d0 = d1;
                P0 = P1;
                Q0 = Q1;
            }
            protectionNpv *= arguments_.claim.amount(null, arguments_.notional.Value, recoveryRate_);

            results_.defaultLegNPV = protectionNpv;

            // premium leg pricing (npv is always positive at this stage)

            double premiumNpv = 0.0, defaultAccrualNpv = 0.0;
            double?accruedAmount = null;

            for (int i = 0; i < arguments_.leg.Count; ++i)
            {
                FixedRateCoupon coupon = arguments_.leg[i] as FixedRateCoupon;

                Utils.QL_REQUIRE(coupon.dayCounter() == dc ||
                                 coupon.dayCounter() == dc1 ||
                                 coupon.dayCounter() == dc2, () =>
                                 "ISDA engine requires a coupon day counter Act/365Fixed "
                                 + "or Act/360 (" + coupon.dayCounter() + ")");

                // premium coupons

                if (!arguments_.leg[i].hasOccurred(evalDate, includeSettlementDateFlows_))
                {
                    double x1 = coupon.amount();
                    double x2 = discountCurve_.link.discount(coupon.date());
                    double x3 = probability_.link.survivalProbability(coupon.date() - 1);

                    // accrual
                    if (accruedAmount == null)
                    {
                        if (evalDate + 1 == coupon.date())
                        {
                            accruedAmount = 0.0;
                            premiumNpv   -= coupon.accruedPeriod(evalDate + 1) *
                                            coupon.nominal() *
                                            coupon.rate();
                        }
                        else
                        {
                            accruedAmount = coupon.accruedPeriod(evalDate + 1) *
                                            coupon.nominal() *
                                            coupon.rate();
                        }
                    }

                    premiumNpv += x1 * x2 * x3;
                }

                // default accruals

                if (!new simple_event(coupon.accrualEndDate())
                    .hasOccurred(effectiveProtectionStart, false))
                {
                    Date   start  = Date.Max(coupon.accrualStartDate(), effectiveProtectionStart) - 1;
                    Date   end    = coupon.date() - 1;
                    double tstart = discountCurve_.link.timeFromReference(coupon.accrualStartDate() - 1) -
                                    (accrualBias_ == AccrualBias.HalfDayBias ? 1.0 / 730.0 : 0.0);
                    List <Date> localNodes = new List <Date>();
                    localNodes.Add(start);
                    //add intermediary nodes, if any
                    if (forwardsInCouponPeriod_ == ForwardsInCouponPeriod.Piecewise)
                    {
                        foreach (Date node in nodes)
                        {
                            if (node > start && node < end)
                            {
                                localNodes.Add(node);
                            }
                        }
                        //std::vector<Date>::const_iterator it0 = std::upper_bound(nodes.begin(), nodes.end(), start);
                        //std::vector<Date>::const_iterator it1 = std::lower_bound(nodes.begin(), nodes.end(), end);
                        //localNodes.insert(localNodes.end(), it0, it1);
                    }
                    localNodes.Add(end);

                    double defaultAccrThisNode = 0.0;
                    Date   firstnode           = localNodes.First();
                    double t0 = discountCurve_.link.timeFromReference(firstnode);
                    P0 = discountCurve_.link.discount(firstnode);
                    Q0 = probability_.link.survivalProbability(firstnode);

                    foreach (Date node in localNodes.Skip(1)) //for (++node; node != localNodes.Last(); ++node)
                    {
                        double t1    = discountCurve_.link.timeFromReference(node);
                        double P1    = discountCurve_.link.discount(node);
                        double Q1    = probability_.link.survivalProbability(node);
                        double fhat  = Math.Log(P0) - Math.Log(P1);
                        double hhat  = Math.Log(Q0) - Math.Log(Q1);
                        double fhphh = fhat + hhat;
                        if (fhphh < 1E-4 && numericalFix_ == NumericalFix.Taylor)
                        {
                            // see above, terms up to (f+h)^3 seem more than enough,
                            // what exactly is implemented in the standard isda C
                            // code ?
                            double fhphhq = fhphh * fhphh;
                            defaultAccrThisNode +=
                                hhat * P0 * Q0 *
                                ((t0 - tstart) *
                                 (1.0 - 0.5 * fhphh + 1.0 / 6.0 * fhphhq -
                                  1.0 / 24.0 * fhphhq * fhphh) +
                                 (t1 - t0) *
                                 (0.5 - 1.0 / 3.0 * fhphh + 1.0 / 8.0 * fhphhq -
                                  1.0 / 30.0 * fhphhq * fhphh));
                        }
                        else
                        {
                            defaultAccrThisNode +=
                                (hhat / (fhphh + nFix)) *
                                ((t1 - t0) * ((P0 * Q0 - P1 * Q1) / (fhphh + nFix) -
                                              P1 * Q1) +
                                 (t0 - tstart) * (P0 * Q0 - P1 * Q1));
                        }

                        t0 = t1;
                        P0 = P1;
                        Q0 = Q1;
                    }
                    defaultAccrualNpv += defaultAccrThisNode * arguments_.notional.Value *
                                         coupon.rate() * 365.0 / 360.0;
                }
            }

            results_.couponLegNPV     = premiumNpv + defaultAccrualNpv;
            results_.accruedAmountNPV = accruedAmount;

            // upfront flow npv

            double upfPVO1 = 0.0;

            results_.upfrontNPV = 0.0;
            if (!arguments_.upfrontPayment.hasOccurred(
                    evalDate, includeSettlementDateFlows_))
            {
                upfPVO1 =
                    discountCurve_.link.discount(arguments_.upfrontPayment.date());
                if (arguments_.upfrontPayment.amount().IsNotEqual(0.0))
                {
                    results_.upfrontNPV = upfPVO1 * arguments_.upfrontPayment.amount();
                }
            }

            results_.accrualRebateNPV = 0.0;
            if (arguments_.accrualRebate != null &&
                arguments_.accrualRebate.amount().IsNotEqual(0.0) &&
                !arguments_.accrualRebate.hasOccurred(evalDate, includeSettlementDateFlows_))
            {
                results_.accrualRebateNPV =
                    discountCurve_.link.discount(arguments_.accrualRebate.date()) *
                    arguments_.accrualRebate.amount();
            }

            double upfrontSign = 1;

            if (arguments_.side == CreditDefaultSwap.Protection.Side.Seller)
            {
                results_.defaultLegNPV    *= -1.0;
                results_.accrualRebateNPV *= -1.0;
                results_.accruedAmountNPV *= -1.0;
            }
            else
            {
                results_.couponLegNPV *= -1.0;
                results_.upfrontNPV   *= -1.0;
            }

            results_.value = results_.defaultLegNPV + results_.couponLegNPV +
                             results_.upfrontNPV + results_.accrualRebateNPV;

            results_.errorEstimate = null;

            if (results_.couponLegNPV.IsNotEqual(0.0))
            {
                results_.fairSpread =
                    -results_.defaultLegNPV * arguments_.spread /
                    (results_.couponLegNPV + results_.accruedAmountNPV + results_.accrualRebateNPV);
            }
            else
            {
                results_.fairSpread = null;
            }

            double upfrontSensitivity = upfPVO1 * arguments_.notional.Value;

            if (upfrontSensitivity.IsNotEqual(0.0))
            {
                results_.fairUpfront =
                    -upfrontSign * (results_.defaultLegNPV + results_.couponLegNPV +
                                    results_.accrualRebateNPV) /
                    upfrontSensitivity;
            }
            else
            {
                results_.fairUpfront = null;
            }

            if (arguments_.spread.IsNotEqual(0.0))
            {
                results_.couponLegBPS =
                    results_.couponLegNPV * Const.BASIS_POINT / arguments_.spread;
            }
            else
            {
                results_.couponLegBPS = null;
            }

            if (arguments_.upfront != null && arguments_.upfront.IsNotEqual(0.0))
            {
                results_.upfrontBPS =
                    results_.upfrontNPV * Const.BASIS_POINT / arguments_.upfront;
            }
            else
            {
                results_.upfrontBPS = null;
            }
        }
Example #11
0
        public CommercialPaper(Type type, double nominal,
                               Schedule fixedSchedule, double fixedRate, DayCounter fixedDayCount,
                               Schedule principalSchedule, BusinessDayConvention?paymentConvention) :
            base(2)
        {
            type_              = type;
            nominal_           = nominal;
            fixedSchedule_     = fixedSchedule;
            fixedRate_         = fixedRate;
            fixedDayCount_     = fixedDayCount;
            principalSchedule_ = principalSchedule;

            if (paymentConvention.HasValue)
            {
                paymentConvention_ = paymentConvention.Value;
            }
            else
            {
                paymentConvention_ = fixedSchedule_.businessDayConvention();
            }

            List <CashFlow> principalLeg = new PricipalLeg(principalSchedule, fixedDayCount)
                                           .withNotionals(nominal)
                                           .withPaymentAdjustment(paymentConvention_)
                                           .withSign(type == Type.Loan ? -1 : 1);

            // temporary
            for (int i = 0; i < principalLeg.Count - 1; i++)
            {
                Principal p = (Principal)principalLeg[i];
                notionals_.Add(p.nominal());
            }

            List <CashFlow> fixedLeg = new FixedRateLeg(fixedSchedule)
                                       .withCouponRates(fixedRate, fixedDayCount)
                                       .withPaymentAdjustment(paymentConvention_)
                                       .withNotionals(notionals_);

            // Discounting Pricipal
            notionals_.Clear();
            double n;

            for (int i = 0; i < fixedLeg.Count; i++)
            {
                FixedRateCoupon c = (FixedRateCoupon)fixedLeg[i];
                n = i > 0 ? notionals_.Last() : c.nominal();
                notionals_.Add(n / (1 + (c.rate() * c.dayCounter().yearFraction(c.referencePeriodStart, c.referencePeriodEnd))));
            }

            // New Leg
            List <CashFlow> discountedFixedLeg = new FixedRateLeg(fixedSchedule)
                                                 .withCouponRates(fixedRate, fixedDayCount)
                                                 .withPaymentAdjustment(paymentConvention_)
                                                 .withNotionals(notionals_);
            // Adjust Principal
            Principal p0 = (Principal)principalLeg[0];

            p0.setAmount(notionals_.Last());

            legs_[0] = discountedFixedLeg;
            legs_[1] = principalLeg;
            if (type_ == Type.Loan)
            {
                payer_[0] = +1;
                payer_[1] = -1;
            }
            else
            {
                payer_[0] = -1;
                payer_[1] = +1;
            }
        }