예제 #1
0
    NthToDefault::NthToDefault(
        const boost::shared_ptr<Basket>& basket,
        Size n,
        Protection::Side side,
        const Schedule& premiumSchedule,
        Rate upfrontRate,
        Rate premiumRate,
        const DayCounter& dayCounter,
        Real nominal,
        bool settlePremiumAccrual
        )
    : basket_(basket), n_(n),
      side_(side), nominal_(nominal),
      premiumSchedule_(premiumSchedule), premiumRate_(premiumRate), 
      upfrontRate_(upfrontRate), 
      dayCounter_(dayCounter), settlePremiumAccrual_(settlePremiumAccrual)
    {
		QL_REQUIRE(n_ <= basket_->size(), 
			"NTD order provided is larger than the basket size.");

        // Basket inception must lie before contract protection start.
        QL_REQUIRE(basket->refDate() <= premiumSchedule.startDate(),
            //using the start date of the schedule might be wrong, think of the CDS rule
            "Basket did not exist before contract start.");

        premiumLeg_ = FixedRateLeg(premiumSchedule)
            .withNotionals(nominal)
            .withCouponRates(premiumRate, dayCounter)
            .withPaymentAdjustment(Unadjusted);

        registerWith(basket_);
    }
예제 #2
0
    AssetSwap::AssetSwap(bool parSwap,
                         const boost::shared_ptr<Bond>& bond,
                         Real bondCleanPrice,
                         Real nonParRepayment,
                         Real gearing,
                         const boost::shared_ptr<IborIndex>& iborIndex,
                         Spread spread,
                         const DayCounter& floatingDayCounter,
                         Date dealMaturity,
                         bool payBondCoupon)
    : Swap(2), bond_(bond), bondCleanPrice_(bondCleanPrice),
      nonParRepayment_(nonParRepayment), spread_(spread), parSwap_(parSwap)
    {
        Schedule tempSch(bond_->settlementDate(),
                         bond_->maturityDate(),
                         iborIndex->tenor(),
                         iborIndex->fixingCalendar(),
                         iborIndex->businessDayConvention(),
                         iborIndex->businessDayConvention(),
                         DateGeneration::Backward,
                         false); // endOfMonth
        if (dealMaturity==Date())
            dealMaturity = bond_->maturityDate();
        QL_REQUIRE(dealMaturity <= tempSch.dates().back(),
                   "deal maturity " << dealMaturity <<
                   " cannot be later than (adjusted) bond maturity " <<
                   tempSch.dates().back());

        // the following might become an input parameter
        BusinessDayConvention paymentAdjustment = 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();
        Real dirtyPrice = bondCleanPrice_ +
                          bond_->accruedAmount(upfrontDate_);

        Real 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 (floatingDayCounter==DayCounter())
            legs_[1] = IborLeg(schedule, iborIndex)
                .withNotionals(notional)
                .withPaymentAdjustment(paymentAdjustment)
                .withGearings(gearing)
                .withSpreads(spread);
        else
            legs_[1] = IborLeg(schedule, iborIndex)
                .withNotionals(notional)
                .withPaymentDayCounter(floatingDayCounter)
                .withPaymentAdjustment(paymentAdjustment)
                .withGearings(gearing)
                .withSpreads(spread);

        for (Leg::const_iterator i=legs_[1].begin(); i<legs_[1].end(); ++i)
            registerWith(*i);

        const Leg& bondLeg = bond_->cashflows();
        Leg::const_iterator i = bondLeg.begin();
        // skip bond redemption
        for (; i<bondLeg.end()-1 && (*i)->date()<=dealMaturity; ++i) {
            // whatever might be the choice for the discounting engine
            // bond flows on upfrontDate_ must be discarded
            bool upfrontDateBondFlows = false;
            if (!(*i)->hasOccurred(upfrontDate_, upfrontDateBondFlows))
                legs_[0].push_back(*i);
        }
        // if the first skipped cashflow is not the redemption
        // and it is a coupon then add the accrued coupon
        if (i<bondLeg.end()-1) {
            shared_ptr<Coupon> c = boost::dynamic_pointer_cast<Coupon>(*i);
            if (c) {
                shared_ptr<CashFlow> accruedCoupon(new
                    SimpleCashFlow(c->accruedAmount(dealMaturity), finalDate));
                legs_[0].push_back(accruedCoupon);
            }
        }
        // add the nonParRepayment_
        shared_ptr<CashFlow> nonParRepaymentFlow(new
            SimpleCashFlow(nonParRepayment_, finalDate));
        legs_[0].push_back(nonParRepaymentFlow);

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

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

        QL_REQUIRE(!legs_[0].empty(), "empty bond leg");
        for (Leg::const_iterator i=legs_[0].begin(); i<legs_[0].end(); ++i)
            registerWith(*i);

        if (payBondCoupon) {
            payer_[0]=-1.0;
            payer_[1]=+1.0;
        } else {
            payer_[0]=+1.0;
            payer_[1]=-1.0;
        }
    }
예제 #3
0
    AssetSwap::AssetSwap(bool payBondCoupon,
                         const shared_ptr<Bond>& bond,
                         Real bondCleanPrice,
                         const shared_ptr<IborIndex>& iborIndex,
                         Spread spread,
                         const Schedule& floatSchedule,
                         const DayCounter& floatingDayCounter,
                         bool parSwap)
    : Swap(2), bond_(bond), bondCleanPrice_(bondCleanPrice),
      nonParRepayment_(100), spread_(spread), parSwap_(parSwap)
    {
        Schedule schedule = floatSchedule;
        if (floatSchedule.empty())
            schedule = Schedule(bond_->settlementDate(),
                                bond_->maturityDate(),
                                iborIndex->tenor(),
                                iborIndex->fixingCalendar(),
                                iborIndex->businessDayConvention(),
                                iborIndex->businessDayConvention(),
                                DateGeneration::Backward,
                                false); // endOfMonth

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

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

        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();
        Real dirtyPrice = bondCleanPrice_ +
                          bond_->accruedAmount(upfrontDate_);

        Real 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 (floatingDayCounter==DayCounter())
            legs_[1] = IborLeg(schedule, iborIndex)
                .withNotionals(notional)
                .withPaymentAdjustment(paymentAdjustment)
                .withSpreads(spread);
        else
            legs_[1] = IborLeg(schedule, iborIndex)
                .withNotionals(notional)
                .withPaymentDayCounter(floatingDayCounter)
                .withPaymentAdjustment(paymentAdjustment)
                .withSpreads(spread);

        for (Leg::const_iterator i=legs_[1].begin(); i<legs_[1].end(); ++i)
            registerWith(*i);

        const Leg& bondLeg = bond_->cashflows();
        for (Leg::const_iterator i=bondLeg.begin(); i<bondLeg.end(); ++i) {
            // whatever might be the choice for the discounting engine
            // bond flows on upfrontDate_ must be discarded
            bool upfrontDateBondFlows = false;
            if (!(*i)->hasOccurred(upfrontDate_, upfrontDateBondFlows))
                legs_[0].push_back(*i);
        }

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

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

        QL_REQUIRE(!legs_[0].empty(), "empty bond leg");
        for (Leg::const_iterator i=legs_[0].begin(); i<legs_[0].end(); ++i)
            registerWith(*i);

        if (payBondCoupon) {
            payer_[0]=-1.0;
            payer_[1]=+1.0;
        } else {
            payer_[0]=+1.0;
            payer_[1]=-1.0;
        }
    }