Пример #1
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;
            }
        }
Пример #2
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;
             }
        }