/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2007 Ferdinando Ametrano Copyright (C) 2006, 2007 Chiara Fornarola Copyright (C) 2007 StatPro Italia srl This file is part of QuantLib, a free-software/open-source library for financial quantitative analysts and developers - http://quantlib.org/ QuantLib is free software: you can redistribute it and/or modify it under the terms of the QuantLib license. You should have received a copy of the license along with this program; if not, please email . The license is also available online at . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #include #include #include #include #include #include namespace QuantLib { AssetSwap::AssetSwap(bool payFixedRate, const boost::shared_ptr& bond, Real bondCleanPrice, const boost::shared_ptr& index, Spread spread, const Handle& discountCurve, const Schedule& floatSch, const DayCounter& floatingDayCounter, bool parSwap) : Swap(discountCurve, Leg(), Leg()), spread_(spread), bondCleanPrice_(bondCleanPrice) { Schedule schedule = floatSch; if (floatSch.empty()) schedule = Schedule(bond->settlementDate(), bond->maturityDate(), index->tenor(), index->fixingCalendar(), index->businessDayConvention(), Unadjusted, true, index->endOfMonth()); // what if this date is not a business day?? // we are assuming it is a business day! upfrontDate_ = schedule.startDate(); Real dirtyPrice = bondCleanPrice_ + bond->accruedAmount(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, and the resulting value of the asset swap spread is different. */ if (parSwap) nominal_ = bond->faceAmount(); else nominal_ = dirtyPrice/100*bond->faceAmount(); // the following should/might be input parameters // ------------------------------------------------- BusinessDayConvention paymentAdjustment = Following; Natural fixingDays = index->fixingDays(); std::vector nominals(1, nominal_); std::vector gearings(1, 1.0); std::vector spreads(1, spread); // ------------------------------------------------- legs_[1] = IborLeg(nominals, schedule, index, floatingDayCounter, paymentAdjustment, fixingDays, gearings, spreads); boost::shared_ptr fictitiousPricer(new BlackIborCouponPricer(Handle())); setCouponPricer(legs_[1], fictitiousPricer); for (Leg::const_iterator i=legs_[1].begin(); icashflows(); for (Leg::const_iterator i=bondLeg.begin(); ihasOccurred(upfrontDate_)) legs_[0].push_back(*i); } QL_REQUIRE(!legs_[0].empty(), "empty bond leg to start with"); // what happen if floatSchedule.endDate() < bond->maturityDate() ?? // special flows if (parSwap) { // upfront on the floating leg Real upfront = (dirtyPrice-100.0)/100.0*nominal_; // we are assuming upfrontDate_ is a business day // see above! boost::shared_ptr 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 = nominal_; Date backPaymentDate = schedule.calendar().adjust( schedule.endDate(), paymentAdjustment); boost::shared_ptr backPaymentCashFlow (new SimpleCashFlow(backPayment, backPaymentDate)); legs_[1].push_back(backPaymentCashFlow); } else { // final nominal exchange Real finalFlow = (dirtyPrice)/100.0*bond->faceAmount(); // we are assuming bond->maturityDate() == schedule.endDate() Date finalDate = schedule.calendar().adjust( schedule.endDate(), paymentAdjustment); //bond->maturityDate(), paymentAdjustment); boost::shared_ptr finalCashFlow (new SimpleCashFlow(finalFlow, finalDate)); legs_[1].push_back(finalCashFlow); } QL_REQUIRE(!legs_[0].empty(), "empty bond leg"); for (Leg::const_iterator i=legs_[0].begin(); i(args); QL_REQUIRE(arguments != 0, "wrong argument type"); arguments->nominal = nominal_; // reset in case it's not set later arguments->currentFloatingCoupon = Null(); Date settlement = termStructure_->referenceDate(); DayCounter counter = termStructure_->dayCounter(); const Leg& fixedCoupons = bondLeg(); arguments->fixedResetTimes = arguments->fixedPayTimes = std::vector