19#include <ql/cashflows/iborcoupon.hpp>
20#include <ql/cashflows/overnightindexedcoupon.hpp>
21#include <ql/indexes/ibor/libor.hpp>
22#include <ql/math/solvers1d/brent.hpp>
23#include <ql/pricingengines/swap/discountingswapengine.hpp>
32class FairSpreadHelper {
34 FairSpreadHelper(
const TenorBasisSwap& swap,
const Handle<YieldTermStructure>& discountCurve, Real nonSpreadLegNPV)
37 engine_ = QuantLib::ext::shared_ptr<PricingEngine>(
new DiscountingSwapEngine(discountCurve));
39 swap.setupArguments(arguments_);
44 Real operator()(Spread tempSpread)
const {
46 Leg::const_iterator it;
48 QuantLib::ext::shared_ptr<QuantExt::SubPeriodsCoupon1> c = QuantLib::ext::dynamic_pointer_cast<QuantExt::SubPeriodsCoupon1>(*it);
49 c->spread() = tempSpread;
56 QuantLib::ext::shared_ptr<PricingEngine>
engine_;
65 const QuantLib::ext::shared_ptr<IborIndex>& payIndex, Spread paySpread,
66 const Period& payFrequency,
const QuantLib::ext::shared_ptr<IborIndex>& recIndex,
67 Spread recSpread,
const Period& recFrequency, DateGeneration::Rule rule,
69 const bool telescopicValueDates)
70 : Swap(2), nominals_(std::vector<Real>(1, nominal)), payIndex_(payIndex), paySpread_(paySpread),
71 payFrequency_(payFrequency), recIndex_(recIndex), recSpread_(recSpread), recFrequency_(recFrequency),
72 includeSpread_(includeSpread), spreadOnRec_(spreadOnRec), type_(type),
73 telescopicValueDates_(telescopicValueDates) {
76 Date terminationDate = effectiveDate + swapTenor;
78 QuantLib::ext::shared_ptr<Libor> payIndexAsLibor = QuantLib::ext::dynamic_pointer_cast<Libor>(
payIndex_);
80 QuantLib::ext::shared_ptr<Libor> recIndexAsLibor = QuantLib::ext::dynamic_pointer_cast<Libor>(
recIndex_);
82 recIndexAsLibor != NULL ? recIndexAsLibor->jointCalendar() :
recIndex_->fixingCalendar();
89 .withConvention(
payIndex_->businessDayConvention())
90 .withTerminationDateConvention(
payIndex_->businessDayConvention())
99 .withConvention(
recIndex_->businessDayConvention())
100 .withTerminationDateConvention(
recIndex_->businessDayConvention())
109 const QuantLib::ext::shared_ptr<IborIndex>& payIndex, Spread paySpread,
110 const Schedule& recSchedule,
const QuantLib::ext::shared_ptr<IborIndex>& recIndex,
112 const bool telescopicValueDates)
113 : Swap(2), nominals_(std::vector<Real>(1, nominal)), paySchedule_(paySchedule), payIndex_(payIndex),
114 paySpread_(paySpread), recSchedule_(recSchedule), recIndex_(recIndex), recSpread_(recSpread),
115 includeSpread_(includeSpread), spreadOnRec_(spreadOnRec), type_(type), telescopicValueDates_(telescopicValueDates) {
122 const QuantLib::ext::shared_ptr<IborIndex>& payIndex, Spread paySpread,
123 const Schedule& recSchedule,
const QuantLib::ext::shared_ptr<IborIndex>& recIndex,
125 const bool telescopicValueDates)
126 : Swap(2), nominals_(nominals), paySchedule_(paySchedule), payIndex_(payIndex),
127 paySpread_(paySpread), recSchedule_(recSchedule), recIndex_(recIndex), recSpread_(recSpread),
128 includeSpread_(includeSpread), spreadOnRec_(spreadOnRec), type_(type), telescopicValueDates_(telescopicValueDates) {
137 QL_REQUIRE(
paySchedule_.tenor() >=
payIndex_->tenor(),
"Expected paySchedule tenor to exceed/equal payIndex tenor");
138 QL_REQUIRE(
recSchedule_.tenor() >=
recIndex_->tenor(),
"Expected recSchedule tenor to exceed/equal recIndex tenor");
143 QuantLib::ext::shared_ptr<OvernightIndex> payIndexON = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(
payIndex_);
156 .withPaymentAdjustment(
payIndex_->businessDayConvention())
157 .withPaymentDayCounter(
payIndex_->dayCounter())
173 "Pay Leg could not be created. Neither overnight nor schedule index tenor match nor spread leg.");
179 QuantLib::ext::shared_ptr<OvernightIndex> recIndexON = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(
recIndex_);
192 .withPaymentAdjustment(
recIndex_->businessDayConvention())
193 .withPaymentDayCounter(
recIndex_->dayCounter())
209 "Rec Leg could not be created. Neither overnight nor schedule index tenor match nor spread leg.");
228 Leg::const_iterator it;
229 for (it = legs_[0].begin(); it != legs_[0].end(); ++it)
231 for (it = legs_[1].begin(); it != legs_[1].end(); ++it)
239 QL_REQUIRE(legBPS_[
idxPay_] != Null<Real>(),
"Pay leg BPS not available");
245 QL_REQUIRE(legNPV_[
idxPay_] != Null<Real>(),
"Pay leg NPV not available");
251 QL_REQUIRE(
fairSpread_[
idxPay_] != Null<Spread>(),
"Pay leg fair spread not available");
257 QL_REQUIRE(legBPS_[
idxRec_] != Null<Real>(),
"Receive leg BPS not available");
263 QL_REQUIRE(legNPV_[
idxRec_] != Null<Real>(),
"Receive leg NPV not available");
269 QL_REQUIRE(
fairSpread_[
idxRec_] != Null<Spread>(),
"Receive leg fair spread not available");
274 Swap::setupExpired();
280 static const Spread basisPoint = 1.0e-4;
281 Swap::fetchResults(r);
293 if (legBPS_[1] != Null<Real>()) {
295 fairSpread_[1] = s - NPV_ / (legBPS_[1] / basisPoint);
303 if (legBPS_[0] != Null<Real>()) {
305 fairSpread_[0] = s - NPV_ / (legBPS_[0] / basisPoint);
309 Handle<YieldTermStructure> discountCurve;
310 QuantLib::ext::shared_ptr<DiscountingSwapEngine>
engine =
311 QuantLib::ext::dynamic_pointer_cast<DiscountingSwapEngine>(
engine_);
313 discountCurve =
engine->discountCurve();
316 if (legBPS_[0] != Null<Real>()) {
318 guess = s - NPV_ / (legBPS_[0] / basisPoint);
322 Real accuracy = 1e-8;
323 FairSpreadHelper f(*
this, discountCurve, legNPV_[1]);
325 fairSpread_[0] = solver.solve(f, accuracy, guess, step);
332 Swap::results::reset();
333 fairSpread = { Null<Spread>(),Null<Spread>() };
QuantLib::ext::shared_ptr< PricingEngine > engine_
const Instrument::results * results_
helper class building a sequence of overnight coupons
OvernightLeg & withTelescopicValueDates(bool telescopicValueDates)
OvernightLeg & withNotionals(Real notional)
OvernightLeg & withSpreads(Spread spread)
helper class building a sequence of sub-period coupons
SubPeriodsLeg1 & withPaymentDayCounter(const DayCounter &dayCounter)
SubPeriodsLeg1 & withType(SubPeriodsCoupon1::Type type)
SubPeriodsLeg1 & withSpread(Spread spread)
SubPeriodsLeg1 & includeSpread(bool includeSpread)
SubPeriodsLeg1 & withPaymentCalendar(const Calendar &calendar)
SubPeriodsLeg1 & withNotionals(const std::vector< Real > ¬ionals)
SubPeriodsLeg1 & withPaymentAdjustment(BusinessDayConvention convention)
std::vector< Spread > fairSpread
TenorBasisSwap(const Date &effectiveDate, Real nominal, const Period &swapTenor, const QuantLib::ext::shared_ptr< IborIndex > &payIndex, Spread paySpread, const Period &payFrequency, const QuantLib::ext::shared_ptr< IborIndex > &recIndex, Spread recSpread, const Period &recFrequency, DateGeneration::Rule rule=DateGeneration::Backward, bool includeSpread=false, bool spreadOnRec=true, QuantExt::SubPeriodsCoupon1::Type type=QuantExt::SubPeriodsCoupon1::Compounding, const bool telescopicValueDates=false)
Constructor with conventions deduced from the indices.
QuantLib::ext::shared_ptr< IborIndex > payIndex_
bool telescopicValueDates_
QuantLib::ext::shared_ptr< IborIndex > recIndex_
const Leg & payLeg() const
Rate fairPayLegSpread() const
std::vector< Spread > fairSpread_
Calendar recIndexCalendar_
Spread fairRecLegSpread() const
const Leg & recLeg() const
void setupExpired() const override
void fetchResults(const PricingEngine::results *) const override
Calendar payIndexCalendar_
QuantExt::SubPeriodsCoupon1::Type type_
std::vector< Real > nominals_
Swap::arguments * arguments_
Single currency tenor basis swap instrument.