Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
lgmbgsflexiswapengine.cpp File Reference
#include "toplevelfixture.hpp"
#include <qle/models/irlgm1fpiecewiseconstanthullwhiteadaptor.hpp>
#include <qle/models/lgm.hpp>
#include <qle/pricingengines/numericlgmbgsflexiswapengine.hpp>
#include <ql/cashflows/floatingratecoupon.hpp>
#include <ql/currencies/europe.hpp>
#include <ql/indexes/ibor/euribor.hpp>
#include <ql/models/shortrate/onefactormodels/gsr.hpp>
#include <ql/pricingengines/swap/discountingswapengine.hpp>
#include <ql/pricingengines/swaption/gaussian1dswaptionengine.hpp>
#include <ql/quotes/simplequote.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/all.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/test/unit_test.hpp>
#include <algorithm>

Go to the source code of this file.

Functions

 BOOST_AUTO_TEST_CASE (testConsistencyWithFlexiSwapPricing)
 
 BOOST_AUTO_TEST_CASE (testConsistencyWithFlexiSwapPricingSeasonedDeal)
 

Function Documentation

◆ BOOST_AUTO_TEST_CASE() [1/2]

BOOST_AUTO_TEST_CASE ( testConsistencyWithFlexiSwapPricing  )

Definition at line 116 of file lgmbgsflexiswapengine.cpp.

116 {
117
118 BOOST_TEST_MESSAGE("Testing LGM BGS Flexi-Swap engine against LGM Flexi-Swap engine...");
119
120 // balance guaranteed swap
121
122 Size nFixed = fixedSchedule.size() - 1, nFloat = floatingSchedule.size() - 1;
123
124 std::vector<std::vector<Real>> trancheNominals{
125 {1000.0, 900.0, 800.0, 700.0, 600.0, 500.0, 400.0, 300.0, 200.0, 100.0},
126 {300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0}};
127
128 // tranche 0
129 QuantLib::ext::shared_ptr<BalanceGuaranteedSwap> bgs0 = QuantLib::ext::make_shared<BalanceGuaranteedSwap>(
130 VanillaSwap::Payer, trancheNominals, fixedSchedule, 0, fixedSchedule, std::vector<Real>(nFixed, strike),
131 Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0), std::vector<Real>(nFloat, 0.0),
132 std::vector<Real>(nFloat, Null<Real>()), std::vector<Real>(nFloat, Null<Real>()), Actual360());
133
134 // tranche 1
135 QuantLib::ext::shared_ptr<BalanceGuaranteedSwap> bgs1 = QuantLib::ext::make_shared<BalanceGuaranteedSwap>(
136 VanillaSwap::Payer, trancheNominals, fixedSchedule, 1, fixedSchedule, std::vector<Real>(nFixed, strike),
137 Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0), std::vector<Real>(nFloat, 0.0),
138 std::vector<Real>(nFloat, Null<Real>()), std::vector<Real>(nFloat, Null<Real>()), Actual360());
139
140 Handle<Quote> minCpr(QuantLib::ext::make_shared<SimpleQuote>(0.05));
141 Handle<Quote> maxCpr(QuantLib::ext::make_shared<SimpleQuote>(0.25));
142
143 auto bgsEngine = QuantLib::ext::make_shared<NumericLgmBgsFlexiSwapEngine>(
144 lgm, 7.0, 16, 7.0, 32, minCpr, maxCpr, yts, QuantExt::NumericLgmBgsFlexiSwapEngine::Method::SingleSwaptions);
145
146 bgs0->setPricingEngine(bgsEngine);
147 Real bgs0Npv = bgs0->NPV();
148 BOOST_TEST_MESSAGE("BGS Npv (tranche 0) = " << bgs0Npv);
149
150 bgs0->setPricingEngine(dscSwapEngine);
151 Real bgs0DscNpv = bgs0->NPV();
152 BOOST_TEST_MESSAGE("BGS discounting engine Npv (tranche 0) = " << bgs0DscNpv);
153
154 bgs1->setPricingEngine(bgsEngine);
155 Real bgs1Npv = bgs1->NPV();
156 BOOST_TEST_MESSAGE("BGS Npv (tranche 1) = " << bgs1Npv);
157
158 bgs1->setPricingEngine(dscSwapEngine);
159 Real bgs1DscNpv = bgs1->NPV();
160 BOOST_TEST_MESSAGE("BGS discounting engine Npv (tranche 1) = " << bgs1DscNpv);
161
162 // flexi swap
163
164 // from manual calculation in Excel
165
166 // tranche 0
167 std::vector<Real> fixedNotionals0{1000.0, 835.0, 683.6666667, 545.0590909, 418.3002273,
168 302.5740795, 197.1236156, 101.2497755, 14.31232412, 0.0};
169 std::vector<Real> floatNotionals0(2 * fixedNotionals0.size(), 0.0);
170 Size i = 0; // remove in C++14 and instead write [i=0, &fixedNotionals] in the capture below
171 std::generate(floatNotionals0.begin(), floatNotionals0.end(),
172 [i, &fixedNotionals0]() mutable { return fixedNotionals0[i++ / 2]; });
173 std::vector<Real> lowerNotionals0{1000.0, 575.0, 283.3333333, 84.46969697, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
174
175 // tranche 1
176 std::vector<Real> fixedNotionals1{300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 235.7342431};
177 std::vector<Real> floatNotionals1(2 * fixedNotionals1.size(), 0.0);
178 i = 0; // see above
179 std::generate(floatNotionals1.begin(), floatNotionals1.end(),
180 [i, &fixedNotionals1]() mutable { return fixedNotionals1[i++ / 2]; });
181 std::vector<Real> lowerNotionals1{300.0, 300.0, 300.0, 300.0, 249.905303,
182 159.6617214, 99.78857586, 60.58592106, 35.34178728, 19.43798301};
183
184 // upper bound for zero CPR
185
186 // tranche 0
187 std::vector<Real> fixedNotionals0ZeroCpr{1000.0, 900.0, 800.0, 700.0, 600.0, 500.0, 400.0, 300.0, 200.0, 100.0};
188 std::vector<Real> floatNotionals0ZeroCpr(2 * fixedNotionals0ZeroCpr.size(), 0.0);
189 i = 0; // see above
190 std::generate(floatNotionals0ZeroCpr.begin(), floatNotionals0ZeroCpr.end(),
191 [i, &fixedNotionals0ZeroCpr]() mutable { return fixedNotionals0ZeroCpr[i++ / 2]; });
192 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap0 = QuantLib::ext::make_shared<FlexiSwap>(
193 VanillaSwap::Payer, fixedNotionals0, floatNotionals0, fixedSchedule, std::vector<Real>(nFixed, strike),
194 Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0), std::vector<Real>(nFloat, 0.0),
195 std::vector<Real>(nFloat, Null<Real>()), std::vector<Real>(nFloat, Null<Real>()), Actual360(), lowerNotionals0,
196 Position::Long);
197 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap0MinCpr0 = QuantLib::ext::make_shared<FlexiSwap>(
198 VanillaSwap::Payer, fixedNotionals0ZeroCpr, floatNotionals0ZeroCpr, fixedSchedule,
199 std::vector<Real>(nFixed, strike), Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0),
200 std::vector<Real>(nFloat, 0.0), std::vector<Real>(nFloat, Null<Real>()),
201 std::vector<Real>(nFloat, Null<Real>()), Actual360(), lowerNotionals1, Position::Long);
202
203 // tranche 1
204 std::vector<Real> fixedNotionals1ZeroCpr(10, 300.0);
205 std::vector<Real> floatNotionals1ZeroCpr(20, 300.0);
206 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap1 = QuantLib::ext::make_shared<FlexiSwap>(
207 VanillaSwap::Payer, fixedNotionals1, floatNotionals1, fixedSchedule, std::vector<Real>(nFixed, strike),
208 Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0), std::vector<Real>(nFloat, 0.0),
209 std::vector<Real>(nFloat, Null<Real>()), std::vector<Real>(nFloat, Null<Real>()), Actual360(), lowerNotionals1,
210 Position::Long);
211 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap1MinCpr0 = QuantLib::ext::make_shared<FlexiSwap>(
212 VanillaSwap::Payer, fixedNotionals1ZeroCpr, floatNotionals1ZeroCpr, fixedSchedule,
213 std::vector<Real>(nFixed, strike), Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0),
214 std::vector<Real>(nFloat, 0.0), std::vector<Real>(nFloat, Null<Real>()),
215 std::vector<Real>(nFloat, Null<Real>()), Actual360(), lowerNotionals1, Position::Long);
216
217 auto flexiEngine = QuantLib::ext::make_shared<NumericLgmFlexiSwapEngine>(
219
220 flexiSwap0->setPricingEngine(flexiEngine);
221 Real flexi0Npv = flexiSwap0->NPV();
222 BOOST_TEST_MESSAGE("Flexi-Swap Npv (tranche 0) = " << flexi0Npv);
223
224 flexiSwap0MinCpr0->setPricingEngine(dscSwapEngine);
225 Real flexi0DscNpv0 = flexiSwap0MinCpr0->NPV();
226 BOOST_TEST_MESSAGE("Flexi-Swap (tranche 0, minCPR=0), discounting engine Npv = " << flexi0DscNpv0);
227
228 flexiSwap1->setPricingEngine(flexiEngine);
229 Real flexi1Npv = flexiSwap1->NPV();
230 BOOST_TEST_MESSAGE("Flexi-Swap Npv (tranche 1) = " << flexi1Npv);
231
232 flexiSwap1MinCpr0->setPricingEngine(dscSwapEngine);
233 Real flexi1DscNpv0 = flexiSwap1MinCpr0->NPV();
234 BOOST_TEST_MESSAGE("Flexi-Swap (tranche 1, minCPR=0), discounting engine Npv = " << flexi1DscNpv0);
235
236 BOOST_CHECK_CLOSE(bgs0Npv, flexi0Npv, 1E-8);
237 BOOST_CHECK_CLOSE(bgs0DscNpv, flexi0DscNpv0, 1E-8);
238 BOOST_CHECK_CLOSE(bgs1Npv, flexi1Npv, 1E-8);
239 BOOST_CHECK_CLOSE(bgs1DscNpv, flexi1DscNpv0, 1E-8);
240
241} // testConsistencyWithFlexiSwap

◆ BOOST_AUTO_TEST_CASE() [2/2]

BOOST_AUTO_TEST_CASE ( testConsistencyWithFlexiSwapPricingSeasonedDeal  )

Definition at line 243 of file lgmbgsflexiswapengine.cpp.

243 {
244
245 BOOST_TEST_MESSAGE("Testing LGM BGS Flexi-Swap engine against LGM Flexi-Swap engine (seasoned deal)...");
246
247 euribor6m->addFixing(Date(6, August, 2015), 0.01); // need for pricing
248
249 // balance guaranteed swap
250
251 Size nFixed = fixedScheduleSeasoned.size() - 1, nFloat = floatingScheduleSeasoned.size() - 1;
252
253 std::vector<std::vector<Real>> trancheNominals{
254 {1000.0, 900.0, 800.0, 700.0, 600.0, 500.0, 400.0, 300.0, 200.0, 100.0},
255 {300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0}};
256
257 // tranche 0
258 QuantLib::ext::shared_ptr<BalanceGuaranteedSwap> bgs0 = QuantLib::ext::make_shared<BalanceGuaranteedSwap>(
259 VanillaSwap::Payer, trancheNominals, fixedScheduleSeasoned, 0, fixedScheduleSeasoned,
260 std::vector<Real>(nFixed, strike), Thirty360(Thirty360::BondBasis), floatingScheduleSeasoned, euribor6m,
261 std::vector<Real>(nFloat, 1.0), std::vector<Real>(nFloat, 0.0), std::vector<Real>(nFloat, Null<Real>()),
262 std::vector<Real>(nFloat, Null<Real>()), Actual360());
263
264 Handle<Quote> minCpr(QuantLib::ext::make_shared<SimpleQuote>(0.05));
265 Handle<Quote> maxCpr(QuantLib::ext::make_shared<SimpleQuote>(0.25));
266
267 auto bgsEngine = QuantLib::ext::make_shared<NumericLgmBgsFlexiSwapEngine>(
268 lgm, 7.0, 16, 7.0, 32, minCpr, maxCpr, yts, QuantExt::NumericLgmBgsFlexiSwapEngine::Method::SingleSwaptions);
269
270 bgs0->setPricingEngine(bgsEngine);
271 Real bgs0Npv = bgs0->NPV();
272 BOOST_TEST_MESSAGE("BGS Npv (tranche 0) = " << bgs0Npv);
273
274 bgs0->setPricingEngine(dscSwapEngine);
275 Real bgs0DscNpv = bgs0->NPV();
276 BOOST_TEST_MESSAGE("BGS discounting engine Npv (tranche 0) = " << bgs0DscNpv);
277
278 // flexi swap
279
280 // from manual calculation in Excel;
281 // the prepayments start in the 3rd fixed period (this is the first period with a future start date)
282
283 // tranche 0
284 std::vector<Real> fixedNotionals0{1000.0, 900, 740.0, 593.4545455, 459.4363636,
285 337.0827273, 225.59325, 124.2288375, 32.31258938, 0.0};
286 std::vector<Real> floatNotionals0(2 * fixedNotionals0.size(), 0.0);
287 Size i = 0; // remove in C++14 and instead write [i=0, &fixedNotionals] in the capture below
288 std::generate(floatNotionals0.begin(), floatNotionals0.end(),
289 [i, &fixedNotionals0]() mutable { return fixedNotionals0[i++ / 2]; });
290 std::vector<Real> lowerNotionals0{1000.0, 900.0, 500.0, 227.2727273, 42.72727273, 0.0, 0.0, 0.0, 0.0, 0.0};
291
292 // upper bound for zero CPR
293
294 // tranche 0
295 std::vector<Real> fixedNotionals0ZeroCpr{1000.0, 900.0, 800.0, 700.0, 600.0, 500.0, 400.0, 300.0, 200.0, 100.0};
296 std::vector<Real> floatNotionals0ZeroCpr(2 * fixedNotionals0ZeroCpr.size(), 0.0);
297 i = 0; // see above
298 std::generate(floatNotionals0ZeroCpr.begin(), floatNotionals0ZeroCpr.end(),
299 [i, &fixedNotionals0ZeroCpr]() mutable { return fixedNotionals0ZeroCpr[i++ / 2]; });
300 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap0 = QuantLib::ext::make_shared<FlexiSwap>(
301 VanillaSwap::Payer, fixedNotionals0, floatNotionals0, fixedScheduleSeasoned, std::vector<Real>(nFixed, strike),
302 Thirty360(Thirty360::BondBasis), floatingScheduleSeasoned, euribor6m, std::vector<Real>(nFloat, 1.0),
303 std::vector<Real>(nFloat, 0.0), std::vector<Real>(nFloat, Null<Real>()),
304 std::vector<Real>(nFloat, Null<Real>()), Actual360(), lowerNotionals0, Position::Long);
305 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap0MinCpr0 = QuantLib::ext::make_shared<FlexiSwap>(
306 VanillaSwap::Payer, fixedNotionals0ZeroCpr, floatNotionals0ZeroCpr, fixedScheduleSeasoned,
307 std::vector<Real>(nFixed, strike), Thirty360(Thirty360::BondBasis), floatingScheduleSeasoned, euribor6m,
308 std::vector<Real>(nFloat, 1.0), std::vector<Real>(nFloat, 0.0), std::vector<Real>(nFloat, Null<Real>()),
309 std::vector<Real>(nFloat, Null<Real>()), Actual360(), lowerNotionals0, Position::Long);
310
311 auto flexiEngine = QuantLib::ext::make_shared<NumericLgmFlexiSwapEngine>(
313
314 flexiSwap0->setPricingEngine(flexiEngine);
315 Real flexi0Npv = flexiSwap0->NPV();
316 BOOST_TEST_MESSAGE("Flexi-Swap Npv (tranche 0) = " << flexi0Npv);
317
318 flexiSwap0MinCpr0->setPricingEngine(dscSwapEngine);
319 Real flexi0DscNpv0 = flexiSwap0MinCpr0->NPV();
320 BOOST_TEST_MESSAGE("Flexi-Swap (tranche 0, minCPR=0), discounting engine Npv = " << flexi0DscNpv0);
321
322 BOOST_CHECK_CLOSE(bgs0Npv, flexi0Npv, 1E-8);
323 BOOST_CHECK_CLOSE(bgs0DscNpv, flexi0DscNpv0, 1E-8);
324} // testConsistencyWithFlexiSwap