/// <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();
        }
        /// <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();
        }
Beispiel #3
0
        public AssetSwap(bool parAssetSwap,
                         Bond bond,
                         double bondCleanPrice,
                         double nonParRepayment,
                         double gearing,
                         IborIndex iborIndex,
                         double spread = 0.0,
                         DayCounter floatingDayCount = null,
                         Date dealMaturity           = null,
                         bool payBondCoupon          = false)
            : base(2)
        {
            bond_            = bond;
            bondCleanPrice_  = bondCleanPrice;
            nonParRepayment_ = nonParRepayment;
            spread_          = spread;
            parSwap_         = parAssetSwap;

            Schedule tempSch = new Schedule(bond_.settlementDate(),
                                            bond_.maturityDate(),
                                            iborIndex.tenor(),
                                            iborIndex.fixingCalendar(),
                                            iborIndex.businessDayConvention(),
                                            iborIndex.businessDayConvention(),
                                            DateGeneration.Rule.Backward,
                                            false); // endOfMonth

            if (dealMaturity == null)
            {
                dealMaturity = bond_.maturityDate();
            }

            Utils.QL_REQUIRE(dealMaturity <= tempSch.dates().Last(), () =>
                             "deal maturity " + dealMaturity +
                             " cannot be later than (adjusted) bond maturity " +
                             tempSch.dates().Last());
            Utils.QL_REQUIRE(dealMaturity > tempSch.dates()[0], () =>
                             "deal maturity " + dealMaturity +
                             " must be later than swap start date " +
                             tempSch.dates()[0]);

            // the following might become an input parameter
            BusinessDayConvention paymentAdjustment = BusinessDayConvention.Following;

            Date     finalDate = tempSch.calendar().adjust(dealMaturity, paymentAdjustment);
            Schedule schedule  = tempSch.until(finalDate);

            // bondCleanPrice must be the (forward) clean price
            // at the floating schedule start date
            upfrontDate_ = schedule.startDate();
            double dirtyPrice = bondCleanPrice_ +
                                bond_.accruedAmount(upfrontDate_);

            double notional = bond_.notional(upfrontDate_);

            /* In the market asset swap, the bond is purchased in return for
             * payment of the full price. The notional of the floating leg is
             * then scaled by the full price. */
            if (!parSwap_)
            {
                notional *= dirtyPrice / 100.0;
            }

            if (floatingDayCount == null)
            {
                legs_[1] = new IborLeg(schedule, iborIndex)
                           .withSpreads(spread)
                           .withGearings(gearing)
                           .withNotionals(notional)
                           .withPaymentAdjustment(paymentAdjustment);
            }
            else
            {
                legs_[1] = new IborLeg(schedule, iborIndex)
                           .withSpreads(spread)
                           .withGearings(gearing)
                           .withPaymentDayCounter(floatingDayCount)
                           .withNotionals(notional)
                           .withPaymentAdjustment(paymentAdjustment);
            }

            foreach (CashFlow c in legs_[1])
            {
                c.registerWith(update);
            }


            List <CashFlow> bondLeg = bond_.cashflows();
            // skip bond redemption
            int i;

            for (i = 0; i < bondLeg.Count && bondLeg[i].date() <= dealMaturity; ++i)
            {
                // whatever might be the choice for the discounting engine
                // bond flows on upfrontDate_ must be discarded
                bool upfrontDateBondFlows = false;
                if (!bondLeg[i].hasOccurred(upfrontDate_, upfrontDateBondFlows))
                {
                    legs_[0].Add(bondLeg[i]);
                }
            }
            // if the first skipped cashflow is not the redemption
            // and it is a coupon then add the accrued coupon
            if (i < bondLeg.Count - 1)
            {
                Coupon c = bondLeg[i] as Coupon;
                if (c != null)
                {
                    CashFlow accruedCoupon = new SimpleCashFlow(c.accruedAmount(dealMaturity), finalDate);
                    legs_[0].Add(accruedCoupon);
                }
            }
            // add the nonParRepayment_
            CashFlow nonParRepaymentFlow = new SimpleCashFlow(nonParRepayment_, finalDate);

            legs_[0].Add(nonParRepaymentFlow);

            Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg to start with");

            // special flows
            if (parSwap_)
            {
                // upfront on the floating leg
                double   upfront         = (dirtyPrice - 100.0) / 100.0 * notional;
                CashFlow upfrontCashFlow = new SimpleCashFlow(upfront, upfrontDate_);
                legs_[1].Insert(0, upfrontCashFlow);
                // backpayment on the floating leg
                // (accounts for non-par redemption, if any)
                double   backPayment         = notional;
                CashFlow backPaymentCashFlow = new SimpleCashFlow(backPayment, finalDate);
                legs_[1].Add(backPaymentCashFlow);
            }
            else
            {
                // final notional exchange
                CashFlow finalCashFlow = new SimpleCashFlow(notional, finalDate);
                legs_[1].Add(finalCashFlow);
            }

            Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg");

            foreach (CashFlow c in legs_[0])
            {
                c.registerWith(update);
            }

            if (payBondCoupon)
            {
                payer_[0] = -1.0;
                payer_[1] = +1.0;
            }
            else
            {
                payer_[0] = +1.0;
                payer_[1] = -1.0;
            }
        }
Beispiel #4
0
        public AssetSwap(bool payBondCoupon,
                         Bond bond,
                         double bondCleanPrice,
                         IborIndex iborIndex,
                         double spread,
                         Schedule floatSchedule      = null,
                         DayCounter floatingDayCount = null,
                         bool parAssetSwap           = true)
            : base(2)
        {
            bond_            = bond;
            bondCleanPrice_  = bondCleanPrice;
            nonParRepayment_ = 100;
            spread_          = spread;
            parSwap_         = parAssetSwap;

            Schedule schedule = floatSchedule;

            if (floatSchedule == null)
            {
                schedule = new Schedule(bond_.settlementDate(),
                                        bond_.maturityDate(),
                                        iborIndex.tenor(),
                                        iborIndex.fixingCalendar(),
                                        iborIndex.businessDayConvention(),
                                        iborIndex.businessDayConvention(),
                                        DateGeneration.Rule.Backward,
                                        false); // endOfMonth
            }
            // the following might become an input parameter
            BusinessDayConvention paymentAdjustment = BusinessDayConvention.Following;

            Date finalDate           = schedule.calendar().adjust(schedule.endDate(), paymentAdjustment);
            Date adjBondMaturityDate = schedule.calendar().adjust(bond_.maturityDate(), paymentAdjustment);

            Utils.QL_REQUIRE(finalDate == adjBondMaturityDate, () =>
                             "adjusted schedule end date (" +
                             finalDate +
                             ") must be equal to adjusted bond maturity date (" +
                             adjBondMaturityDate + ")");

            // bondCleanPrice must be the (forward) clean price
            // at the floating schedule start date
            upfrontDate_ = schedule.startDate();
            double dirtyPrice = bondCleanPrice_ +
                                bond_.accruedAmount(upfrontDate_);

            double notional = bond_.notional(upfrontDate_);

            /* In the market asset swap, the bond is purchased in return for
             * payment of the full price. The notional of the floating leg is
             * then scaled by the full price. */
            if (!parSwap_)
            {
                notional *= dirtyPrice / 100.0;
            }

            if (floatingDayCount == null)
            {
                legs_[1] = new IborLeg(schedule, iborIndex)
                           .withSpreads(spread)
                           .withNotionals(notional)
                           .withPaymentAdjustment(paymentAdjustment);
            }
            else
            {
                legs_[1] = new IborLeg(schedule, iborIndex)
                           .withSpreads(spread)
                           .withPaymentDayCounter(floatingDayCount)
                           .withNotionals(notional)
                           .withPaymentAdjustment(paymentAdjustment);
            }

            foreach (CashFlow c in legs_[1])
            {
                c.registerWith(update);
            }

            List <CashFlow> bondLeg = bond_.cashflows();

            foreach (CashFlow c in bondLeg)
            {
                // whatever might be the choice for the discounting engine
                // bond flows on upfrontDate_ must be discarded
                bool upfrontDateBondFlows = false;
                if (!(c.hasOccurred(upfrontDate_, upfrontDateBondFlows)))
                {
                    legs_[0].Add(c);
                }
            }

            Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg to start with");

            // special flows
            if (parSwap_)
            {
                // upfront on the floating leg
                double   upfront         = (dirtyPrice - 100.0) / 100.0 * notional;
                CashFlow upfrontCashFlow = new SimpleCashFlow(upfront, upfrontDate_);
                legs_[1].Insert(0, upfrontCashFlow);
                // backpayment on the floating leg
                // (accounts for non-par redemption, if any)
                double   backPayment         = notional;
                CashFlow backPaymentCashFlow = new SimpleCashFlow(backPayment, finalDate);
                legs_[1].Add(backPaymentCashFlow);
            }
            else
            {
                // final notional exchange
                CashFlow finalCashFlow = new SimpleCashFlow(notional, finalDate);
                legs_[1].Add(finalCashFlow);
            }

            Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg");

            foreach (CashFlow c in legs_[0])
            {
                c.registerWith(update);
            }

            if (payBondCoupon)
            {
                payer_[0] = -1.0;
                payer_[1] = +1.0;
            }
            else
            {
                payer_[0] = +1.0;
                payer_[1] = -1.0;
            }
        }
Beispiel #5
0
        public CPISwap(Type type,
                       double nominal,
                       bool subtractInflationNominal,
                       // float+spread leg
                       double spread,
                       DayCounter floatDayCount,
                       Schedule floatSchedule,
                       BusinessDayConvention floatPaymentRoll,
                       int fixingDays,
                       IborIndex floatIndex,
                       // fixed x inflation leg
                       double fixedRate,
                       double baseCPI,
                       DayCounter fixedDayCount,
                       Schedule fixedSchedule,
                       BusinessDayConvention fixedPaymentRoll,
                       Period observationLag,
                       ZeroInflationIndex fixedIndex,
                       InterpolationType observationInterpolation = InterpolationType.AsIndex,
                       double?inflationNominal = null)
            : base(2)
        {
            type_    = type;
            nominal_ = nominal;
            subtractInflationNominal_ = subtractInflationNominal;
            spread_                   = spread;
            floatDayCount_            = floatDayCount;
            floatSchedule_            = floatSchedule;
            floatPaymentRoll_         = floatPaymentRoll;
            fixingDays_               = fixingDays;
            floatIndex_               = floatIndex;
            fixedRate_                = fixedRate;
            baseCPI_                  = baseCPI;
            fixedDayCount_            = fixedDayCount;
            fixedSchedule_            = fixedSchedule;
            fixedPaymentRoll_         = fixedPaymentRoll;
            fixedIndex_               = fixedIndex;
            observationLag_           = observationLag;
            observationInterpolation_ = observationInterpolation;

            Utils.QL_REQUIRE(floatSchedule_.Count > 0, () => "empty float schedule");
            Utils.QL_REQUIRE(fixedSchedule_.Count > 0, () => "empty fixed schedule");
            // todo if roll!=unadjusted then need calendars ...

            inflationNominal_ = inflationNominal ?? nominal_;

            List <CashFlow> floatingLeg;

            if (floatSchedule_.Count > 1)
            {
                floatingLeg = new IborLeg(floatSchedule_, floatIndex_)
                              .withFixingDays(fixingDays_)
                              .withPaymentDayCounter(floatDayCount_)
                              .withSpreads(spread_)
                              .withNotionals(nominal_)
                              .withPaymentAdjustment(floatPaymentRoll_);
            }
            else
            {
                floatingLeg = new List <CashFlow>();
            }

            if (floatSchedule_.Count == 1 ||
                !subtractInflationNominal_ ||
                (subtractInflationNominal && Math.Abs(nominal_ - inflationNominal_) > 0.00001)
                )
            {
                Date payNotional;
                if (floatSchedule_.Count == 1)
                {
                    // no coupons
                    payNotional = floatSchedule_[0];
                    payNotional = floatSchedule_.calendar().adjust(payNotional, floatPaymentRoll_);
                }
                else
                {
                    // use the pay date of the last coupon
                    payNotional = floatingLeg.Last().date();
                }

                double   floatAmount = subtractInflationNominal_ ? nominal_ - inflationNominal_ : nominal_;
                CashFlow nf          = new SimpleCashFlow(floatAmount, payNotional);
                floatingLeg.Add(nf);
            }

            // a CPIleg know about zero legs and inclusion of base inflation notional
            List <CashFlow> cpiLeg = new CPILeg(fixedSchedule_, fixedIndex_, baseCPI_, observationLag_)
                                     .withFixedRates(fixedRate_)
                                     .withPaymentDayCounter(fixedDayCount_)
                                     .withObservationInterpolation(observationInterpolation_)
                                     .withSubtractInflationNominal(subtractInflationNominal_)
                                     .withNotionals(inflationNominal_)
                                     .withPaymentAdjustment(fixedPaymentRoll_);

            foreach (CashFlow cashFlow in cpiLeg)
            {
                cashFlow.registerWith(update);
            }

            if (floatingLeg.Count > 0)
            {
                foreach (CashFlow cashFlow in floatingLeg)
                {
                    cashFlow.registerWith(update);
                }
            }

            legs_[0] = cpiLeg;
            legs_[1] = floatingLeg;


            if (type_ == Type.Payer)
            {
                payer_[0] = 1.0;
                payer_[1] = -1.0;
            }
            else
            {
                payer_[0] = -1.0;
                payer_[1] = 1.0;
            }
        }