78 {
79
80 BOOST_TEST_MESSAGE("Testing QuantExt Bond TRS pricing.");
81
82 Settings::instance().evaluationDate() = Date(5, Feb, 2016);
83 Date today = Settings::instance().evaluationDate();
84 Calendar calendar = TARGET();
85
86
87 Handle<Quote> rateQuote(QuantLib::ext::make_shared<SimpleQuote>(data.benchmarkRate));
88 Handle<Quote> issuerSpreadQuote(QuantLib::ext::make_shared<SimpleQuote>(data.defaultSpread));
89 DayCounter dc = Actual365Fixed();
90 Handle<YieldTermStructure> yieldCurve(QuantLib::ext::make_shared<FlatForward>(today, rateQuote, dc, Compounded, Annual));
91 Handle<DefaultProbabilityTermStructure> defaultCurve(
92 QuantLib::ext::make_shared<FlatHazardRate>(today, issuerSpreadQuote, dc));
93 Handle<Quote> bondSpecificSpread(QuantLib::ext::make_shared<SimpleQuote>(data.securitySpread));
94 Handle<Quote> recoveryRateQuote(QuantLib::ext::make_shared<SimpleQuote>(0.4));
95
96
97 Handle<Quote> oisQuote(QuantLib::ext::make_shared<SimpleQuote>(data.oisRate));
98 Handle<YieldTermStructure> oisCurve(QuantLib::ext::make_shared<FlatForward>(today, oisQuote, dc, Compounded, Annual));
99 Handle<Quote> iborQuote(QuantLib::ext::make_shared<SimpleQuote>(data.euriborRate));
100 Handle<YieldTermStructure> iborCurve(QuantLib::ext::make_shared<FlatForward>(today, iborQuote, dc, Compounded, Annual));
101
102
103 Date startDate = data.seasoned ? today - 3 * Months : TARGET().advance(today, 2 * Days);
104 Date endDate = startDate + Period(5, Years);
105 BusinessDayConvention bdc = Following;
106 BusinessDayConvention bdcEnd = bdc;
107 DateGeneration::Rule rule = DateGeneration::Forward;
108 bool endOfMonth = false;
109 Date firstDate, lastDate;
110 Schedule schedule(startDate, endDate, 1 * Years, calendar, bdc, bdcEnd, rule, endOfMonth, firstDate, lastDate);
111 Real redemption = 100.0;
112 Real couponRate = 0.04;
113 Leg leg =
114 FixedRateLeg(schedule).withNotionals(redemption).withCouponRates(couponRate, dc).withPaymentAdjustment(bdc);
115
116 QuantLib::ext::shared_ptr<QuantLib::Bond> bond(QuantLib::ext::make_shared<QuantLib::Bond>(0, calendar, startDate, leg));
117
118
119 std::string secId = "SECURITY";
120 QuantLib::ext::shared_ptr<QuantExt::BondIndex> bondIndex = QuantLib::ext::make_shared<QuantExt::BondIndex>(
121 secId, false, false, NullCalendar(), bond, yieldCurve, defaultCurve, recoveryRateQuote, bondSpecificSpread,
122 Handle<YieldTermStructure>(), false);
123 Date bondFixingDate(5, Nov, 2015);
124 bondIndex->addFixing(bondFixingDate, data.bondFixing);
125
126
127 Period timeStep = 1 * Months;
128 QuantLib::ext::shared_ptr<PricingEngine> bondEngine(QuantLib::ext::make_shared<QuantExt::DiscountingRiskyBondEngine>(
129 yieldCurve, defaultCurve, recoveryRateQuote, bondSpecificSpread, timeStep));
130 bond->setPricingEngine(bondEngine);
131
132
133 Schedule floatingSchedule(startDate, endDate, 6 * Months, calendar, bdc, bdcEnd, rule, endOfMonth, firstDate,
134 lastDate);
135 QuantLib::ext::shared_ptr<IborIndex> iborIndex = QuantLib::ext::make_shared<Euribor>(6 * Months, iborCurve);
136 Leg fundingLeg = IborLeg(schedule, iborIndex).withNotionals(redemption);
137 Date iborFixingDate(3, Nov, 2015);
138 iborIndex->addFixing(iborFixingDate, 0.03);
139 Leg fundingNotionalLeg;
140
141
142 std::vector<Date> valuationDates, paymentDates;
143 for (const auto& d : floatingSchedule.dates()) {
144 valuationDates.push_back(d);
145 if (d != floatingSchedule.dates().front())
146 paymentDates.push_back(d);
147 }
148
149
150 QuantLib::ext::shared_ptr<BondTRS> trs = QuantLib::ext::make_shared<BondTRS>(
151 bondIndex, 1.0, Null<Real>(), std::vector<QuantLib::Leg>{fundingLeg, fundingNotionalLeg},
152 true, valuationDates, paymentDates);
154 trs->setPricingEngine(trsEngine);
155
156
157 QuantLib::ext::shared_ptr<QuantLib::Bond> floater(QuantLib::ext::make_shared<QuantLib::Bond>(0, calendar, startDate, fundingLeg));
158 Handle<Quote> floaterIssuerSpreadQuote(QuantLib::ext::make_shared<SimpleQuote>(0.0));
159 Handle<DefaultProbabilityTermStructure> floaterDefaultCurve(
160 QuantLib::ext::make_shared<FlatHazardRate>(today, floaterIssuerSpreadQuote, dc));
161 Handle<Quote> floaterSpecificSpread(QuantLib::ext::make_shared<SimpleQuote>(data.securitySpread));
162 Handle<Quote> floaterRecoveryRateQuote(QuantLib::ext::make_shared<SimpleQuote>(0.0));
163 QuantLib::ext::shared_ptr<PricingEngine> floaterEngine(QuantLib::ext::make_shared<QuantExt::DiscountingRiskyBondEngine>(
164 yieldCurve, floaterDefaultCurve, floaterRecoveryRateQuote, floaterSpecificSpread, timeStep));
165 floater->setPricingEngine(floaterEngine);
166
167 std::ostringstream output;
168
169
170 Real bondNpv = bond->NPV();
171
172 output << "Bond NPV = " << bondNpv << "\n";
173 output << "Floater NPV = " << floater->NPV() << "\n";
174 output << "TRS NPV = " << trs->NPV() << "\n";
175 output << "Bond + TRS - Floater = " << bondNpv + trs->NPV() - floater->NPV() << "\n";
176
177 BOOST_TEST_MESSAGE(output.str());
178
179
180
181
182
183
184 BOOST_CHECK_SMALL((bondNpv + trs->NPV() - floater->NPV()) - (bondNpv - redemption), 1.0);
185}
Discounting Bond TRS Engine.