19#include <boost/test/unit_test.hpp>
21#include <oret/toplevelfixture.hpp>
32#include <ql/cashflows/couponpricer.hpp>
33#include <ql/cashflows/iborcoupon.hpp>
34#include <ql/currencies/europe.hpp>
35#include <ql/exercise.hpp>
36#include <ql/experimental/coupons/strippedcapflooredcoupon.hpp>
37#include <ql/indexes/ibor/euribor.hpp>
38#include <ql/indexes/iborindex.hpp>
39#include <ql/indexes/swap/euriborswap.hpp>
40#include <ql/instruments/makevanillaswap.hpp>
41#include <ql/instruments/nonstandardswap.hpp>
42#include <ql/math/optimization/levenbergmarquardt.hpp>
43#include <ql/models/shortrate/calibrationhelpers/swaptionhelper.hpp>
44#include <ql/pricingengines/swaption/blackswaptionengine.hpp>
45#include <ql/termstructures/credit/flathazardrate.hpp>
46#include <ql/termstructures/volatility/swaption/swaptionconstantvol.hpp>
47#include <ql/termstructures/yield/flatforward.hpp>
48#include <ql/time/calendars/target.hpp>
49#include <ql/time/daycounters/actualactual.hpp>
50#include <ql/timegrid.hpp>
52#include <boost/accumulators/accumulators.hpp>
53#include <boost/accumulators/statistics/mean.hpp>
54#include <boost/accumulators/statistics/stats.hpp>
56#include <boost/timer/timer.hpp>
61using namespace boost::accumulators;
63using namespace boost::unit_test_framework;
66BOOST_FIXTURE_TEST_SUITE(OREDataTestSuite, ore::test::TopLevelFixture)
68BOOST_AUTO_TEST_SUITE(RiskParticipationAgreementTests)
71void runTest(
const std::vector<Real>& nominals,
const bool isPayer,
const Real errorTol,
72 const std::vector<Real> cachedSimResults = {}) {
74 Date today(6, Jun, 2019);
75 Settings::instance().evaluationDate() = today;
77 auto dsc = Handle<YieldTermStructure>(QuantLib::ext::make_shared<FlatForward>(today, 0.01, ActualActual(ActualActual::ISDA)));
78 auto fwd = Handle<YieldTermStructure>(QuantLib::ext::make_shared<FlatForward>(today, 0.02, ActualActual(ActualActual::ISDA)));
80 Handle<DefaultProbabilityTermStructure>(QuantLib::ext::make_shared<FlatHazardRate>(today, 0.0050, ActualActual(ActualActual::ISDA)));
81 auto blackVol = Handle<SwaptionVolatilityStructure>(
82 QuantLib::ext::make_shared<ConstantSwaptionVolatility>(today, TARGET(), Following, 0.0050, ActualActual(ActualActual::ISDA), Normal));
84 auto swapIndexBase = QuantLib::ext::make_shared<EuriborSwapIsdaFixA>(10 * Years, fwd, dsc);
88 std::vector<Real> fixedNominals(nominals);
89 fixedNominals.resize(20, nominals.back());
90 std::vector<Real> fixedRates(20, 0.03);
91 std::vector<Real> floatNominals;
92 for (
auto const& n : fixedNominals) {
93 floatNominals.push_back(n);
94 floatNominals.push_back(n);
97 QuantLib::ext::shared_ptr<VanillaSwap> tmp = MakeVanillaSwap(20 * Years, swapIndexBase->iborIndex(), 0.03);
98 QuantLib::ext::shared_ptr<Swap> underlying = QuantLib::ext::make_shared<NonstandardSwap>(
99 isPayer ? VanillaSwap::Payer : VanillaSwap::Receiver, fixedNominals, floatNominals, tmp->fixedSchedule(),
100 fixedRates, tmp->fixedDayCount(), tmp->floatingSchedule(), tmp->iborIndex(), std::vector<Real>(40, 1.0),
101 std::vector<Real>(40, 0.0), tmp->floatingDayCount());
103 underlying->setPricingEngine(QuantLib::ext::make_shared<DiscountingSwapEngine>(dsc));
104 BOOST_TEST_MESSAGE(
"Underlying NPV = " << underlying->NPV());
108 Real participationRate = 0.8;
109 Real recoveryRate = 0.2;
110 Date feePayDate = today + 20;
113 QuantLib::ext::make_shared<FixedRateCoupon>(feePayDate, nominals.front(), 0.02, ActualActual(ActualActual::ISDA), today, feePayDate));
115 QuantLib::ext::shared_ptr<RiskParticipationAgreement> rpa = QuantLib::ext::make_shared<RiskParticipationAgreement>(
116 std::vector<Leg>{underlying->leg(0), underlying->leg(1)}, std::vector<bool>{isPayer, !isPayer},
117 std::vector<std::string>{
"EUR",
"EUR"}, std::vector<Leg>{fee},
true, std::vector<std::string>{
"EUR"},
118 participationRate, today, underlying->maturityDate(),
true, recoveryRate);
122 std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>> basket;
123 std::vector<Date> expiryDates;
124 for (Size i = 1; i < 20; ++i) {
125 QuantLib::ext::shared_ptr<BlackCalibrationHelper>
helper = QuantLib::ext::make_shared<SwaptionHelper>(
126 i * Years, (20 - i) * Years, Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(0.0050)),
127 swapIndexBase->iborIndex(), 1 * Years, swapIndexBase->dayCounter(),
128 swapIndexBase->iborIndex()->dayCounter(), dsc, BlackCalibrationHelper::RelativePriceError,
129 fixedRates.front(), 1.0, Normal);
131 expiryDates.push_back(
132 QuantLib::ext::static_pointer_cast<SwaptionHelper>(
helper)->swaption()->exercise()->dates().back());
134 std::vector<Date> stepDates(expiryDates.begin(), expiryDates.end() - 1);
135 Array stepTimes(stepDates.size());
136 for (Size i = 0; i < stepDates.size(); ++i) {
137 stepTimes[i] = dsc->timeFromReference(stepDates[i]);
139 auto lgm_p = QuantLib::ext::make_shared<IrLgm1fPiecewiseConstantHullWhiteAdaptor>(
140 EURCurrency(), dsc, stepTimes, Array(stepTimes.size() + 1, 0.0050), stepTimes,
141 Array(stepTimes.size() + 1, 0.0));
142 lgm_p->shift() = -lgm_p->H(20.0);
143 auto lgm = QuantLib::ext::make_shared<LGM>(lgm_p);
145 auto rpaEngine = QuantLib::ext::make_shared<NumericLgmRiskParticipationAgreementEngine>(
146 "EUR", std::map<std::string, Handle<YieldTermStructure>>{{
"EUR", dsc}}, std::map<std::string, Handle<Quote>>(),
147 lgm, 3.0, 10, 3.0, 10, def, Handle<Quote>());
151 rpa->setPricingEngine(rpaEngine);
155 boost::timer::cpu_timer timer;
156 std::vector<Date> gridDates = rpa->result<std::vector<Date>>(
"GridDates");
157 std::vector<Real> epe_engine = rpa->result<std::vector<Real>>(
"OptionNpvs");
159 BOOST_TEST_MESSAGE(
"EPE calculation in numeric lgm engine took " << timer.elapsed().wall * 1e-6 <<
"ms");
163 std::vector<Date> evalDates;
164 for (Size i = 0; i < gridDates.size() - 1; ++i) {
165 evalDates.push_back(gridDates[i] + (gridDates[i + 1] - gridDates[i]) / 2);
168 std::vector<Date> expectedEvalDates{
169 Date(7, September, 2019), Date(10, March, 2020), Date(9, September, 2020), Date(11, March, 2021),
170 Date(9, September, 2021), Date(11, March, 2022), Date(10, September, 2022), Date(13, March, 2023),
171 Date(11, September, 2023), Date(11, March, 2024), Date(9, September, 2024), Date(11, March, 2025),
172 Date(9, September, 2025), Date(11, March, 2026), Date(9, September, 2026), Date(11, March, 2027),
173 Date(9, September, 2027), Date(11, March, 2028), Date(11, September, 2028), Date(12, March, 2029),
174 Date(10, September, 2029), Date(11, March, 2030), Date(9, September, 2030), Date(11, March, 2031),
175 Date(9, September, 2031), Date(10, March, 2032), Date(9, September, 2032), Date(11, March, 2033),
176 Date(10, September, 2033), Date(13, March, 2034), Date(11, September, 2034), Date(12, March, 2035),
177 Date(10, September, 2035), Date(10, March, 2036), Date(9, September, 2036), Date(11, March, 2037),
178 Date(9, September, 2037), Date(11, March, 2038), Date(9, September, 2038), Date(11, March, 2039)};
180 BOOST_REQUIRE(evalDates.size() == expectedEvalDates.size());
181 for (Size i = 0; i < evalDates.size(); ++i)
182 BOOST_REQUIRE_EQUAL(evalDates[i], expectedEvalDates[i]);
186 std::vector<Real> evalTimes;
187 for (Size i = 0; i < evalDates.size(); ++i) {
188 evalTimes.push_back(dsc->timeFromReference(evalDates[i]));
190 Size nTimes = evalDates.size();
191 std::vector<Real> epe_sim(nTimes);
193 if (cachedSimResults.empty()) {
195 TimeGrid grid(evalTimes.begin(), evalTimes.end());
197 auto swaptionEngineLgm = QuantLib::ext::make_shared<AnalyticLgmSwaptionEngine>(lgm);
198 for (Size i = 0; i < basket.size(); ++i) {
199 basket[i]->setPricingEngine(swaptionEngineLgm);
201 LevenbergMarquardt lm(1E-8, 1E-8, 1E-8);
202 EndCriteria ec(1000, 500, 1E-8, 1E-8, 1E-8);
203 lgm->calibrateVolatilitiesIterative(basket, lm, ec);
207 auto lgm_dsc = QuantLib::ext::make_shared<LgmImpliedYtsFwdFwdCorrected>(lgm, dsc);
208 auto lgm_fwd = QuantLib::ext::make_shared<LgmImpliedYtsFwdFwdCorrected>(lgm, fwd);
210 auto lgmEuribor = swapIndexBase->iborIndex()->clone(Handle<YieldTermStructure>(lgm_fwd));
212 std::vector<Leg> lgmLinkedUnderlying(2);
213 std::set<Date> requiredFixings;
214 for (Size i = 0; i < 2; ++i) {
215 for (
auto const& c : underlying->leg(i)) {
216 auto f = QuantLib::ext::dynamic_pointer_cast<IborCoupon>(c);
218 requiredFixings.insert(f->fixingDate());
219 auto ic = QuantLib::ext::make_shared<IborCoupon>(
220 f->date(), f->nominal(), f->accrualStartDate(), f->accrualEndDate(), f->fixingDays(),
221 lgmEuribor, f->gearing(), f->spread(), f->referencePeriodStart(), f->referencePeriodEnd(),
222 f->dayCounter(), f->isInArrears());
223 ic->setPricer(QuantLib::ext::make_shared<BlackIborCouponPricer>());
224 lgmLinkedUnderlying[i].push_back(ic);
226 lgmLinkedUnderlying[i].push_back(c);
230 Swap lgmUnderlying(lgmLinkedUnderlying, {isPayer, !isPayer});
233 auto lgmSwapEngine = QuantLib::ext::make_shared<DiscountingSwapEngine>(Handle<YieldTermStructure>(lgm_dsc));
234 lgmUnderlying.setPricingEngine(lgmSwapEngine);
235 std::vector<accumulator_set<double, stats<tag::mean>>> acc(nTimes);
236 for (Size p = 0; p < nPaths; ++p) {
237 auto currentFixing = requiredFixings.begin();
238 MultiPath path = pgen.next().value;
239 for (Size i = 0; i < nTimes; ++i) {
240 lgm_dsc->move(evalDates[i], path[0][i + 1]);
241 lgm_fwd->move(evalDates[i], path[0][i + 1]);
242 Settings::instance().evaluationDate() = evalDates[i];
243 while (currentFixing != requiredFixings.end() && evalDates[i] >= *currentFixing) {
245 lgmEuribor->fixingCalendar().adjust(evalDates[i]);
246 lgmEuribor->addFixing(*currentFixing, lgmEuribor->fixing(evalDateAdj),
false);
249 acc[i](std::max(lgmUnderlying.NPV(), 0.0) / lgm->numeraire(evalTimes[i], path[0][i + 1]));
251 Settings::instance().evaluationDate() = today;
252 IndexManager::instance().clearHistory(lgmEuribor->name());
254 for (Size i = 0; i < nTimes; ++i) {
255 epe_sim[i] = mean(acc[i]);
256 BOOST_TEST_MESSAGE(epe_sim[i] << (i < nTimes - 1 ?
"," :
""));
259 BOOST_TEST_MESSAGE(
"EPE calculation via full simulation took " << timer.elapsed().wall * 1e-6 <<
"ms");
261 BOOST_REQUIRE(cachedSimResults.size() == nTimes);
262 for (Size i = 0; i < nTimes; ++i)
263 epe_sim[i] = cachedSimResults[i];
269 BOOST_TEST_MESSAGE(
"date t EPE_engine EPE_sim");
270 for (Size i = 0; i < nTimes; ++i) {
271 BOOST_TEST_MESSAGE(QuantLib::io::iso_date(evalDates[i])
272 <<
" " << evalTimes[i] <<
" " << epe_engine[i] <<
" " << epe_sim[i]);
273 BOOST_CHECK_SMALL(epe_engine[i] - epe_sim[i], errorTol);
274 maxError = std::max(maxError, std::abs(epe_sim[i] - epe_engine[i]));
276 BOOST_TEST_MESSAGE(
"max error = " << maxError);
280 Real npv = rpa->NPV();
281 BOOST_TEST_MESSAGE(
"RPA total NPV (LGM engine) = " << npv);
284 for (Size i = 0; i < gridDates.size() - 1; ++i) {
285 protNpv += epe_engine[i] * def->defaultProbability(gridDates[i], gridDates[i + 1]);
287 protNpv *= participationRate * (1.0 - recoveryRate);
290 for (
auto const& c : fee) {
292 feeNpv += c->amount() * dsc->discount(c->date()) * def->survivalProbability(c->date());
294 auto cpn = QuantLib::ext::dynamic_pointer_cast<Coupon>(c);
296 Date start = std::max(cpn->accrualStartDate(), today);
297 Date end = cpn->accrualEndDate();
299 Date mid = start + (end - start) / 2;
300 feeNpv += cpn->accruedAmount(mid) * dsc->discount(mid) * def->defaultProbability(start, end);
305 BOOST_TEST_MESSAGE(
"Expected NPV = " << protNpv - feeNpv);
306 BOOST_CHECK_CLOSE(npv, protNpv - feeNpv, 1E-8);
310 auto blackEngine = QuantLib::ext::make_shared<AnalyticBlackRiskParticipationAgreementEngine>(
311 "EUR", std::map<std::string, Handle<YieldTermStructure>>{{
"EUR", dsc}}, std::map<std::string, Handle<Quote>>(),
312 def, Handle<Quote>(), blackVol, swapIndexBase,
false, 0.0,
false);
313 rpa->setPricingEngine(blackEngine);
314 Real blackNpv = rpa->NPV();
316 BOOST_TEST_MESSAGE(
"Black NPV = " << blackNpv);
317 BOOST_CHECK_CLOSE(npv, blackNpv, 5.0);
322 runTest({10000.0},
true, 10.0,
323 {0, 1.94889, 15.7715, 24.0619, 54.8255, 55.7279, 95.6096, 91.7498, 133.741, 123.373,
324 164.17, 147.664, 189.878, 166.109, 207.458, 179.875, 220.102, 187.612, 226.417, 190.731,
325 227.738, 188.212, 222.535, 180.287, 214.038, 169.203, 200.895, 154.238, 183.085, 133.985,
326 161.588, 111.699, 135.997, 85.3633, 107.052, 56.2545, 74.7086, 25.7101, 38.9068, 1.31757});
330 runTest({10000.0},
false, 10.0,
331 {1776.41, 1878.45, 1694.92, 1802.31, 1637.38, 1736.49, 1582.74, 1677.57, 1526.22, 1611.41,
332 1463.59, 1542.34, 1396.47, 1467.08, 1322.19, 1388.18, 1244.17, 1303.92, 1159.84, 1214.88,
333 1072.06, 1122.67, 978.803, 1026.29, 882.843, 926.86, 783.296, 824.455, 679.52, 718.399,
334 572.469, 608.334, 463.113, 497.353, 351.281, 384.799, 236.4, 271.088, 119.076, 164.356});
338 runTest({10000.0, 9500.0, 9000.0, 8500.0, 8000.0, 7500.0, 7000.0, 6500.0, 6000.0, 5500.0, 5000.0,
339 4500.0, 4000.0, 3500.0, 3000.0, 2500.0, 2000.0, 1500.0, 1000.0, 500.0, 0.0},
340 true, 5.0, {0, 0.58703, 8.11856, 8.93971, 26.7995, 20.7611, 44.169, 33.6139, 58.2056, 43.9656,
341 67.223, 49.9792, 72.8682, 52.7195, 74.1339, 53.0533, 72.9152, 51.5704, 69.0406, 47.9078,
342 63.6394, 42.9462, 56.4375, 36.8842, 48.762, 30.607, 40.6079, 24.2613, 32.3475, 17.8779,
343 24.4077, 12.3198, 17.092, 7.4161, 10.7417, 3.56567, 5.61611, 1.08903, 1.94534, 0.0658784});
347 runTest({10000.0, 9500.0, 9000.0, 8500.0, 8000.0, 7500.0, 7000.0, 6500.0, 6000.0, 5500.0, 5000.0,
348 4500.0, 4000.0, 3500.0, 3000.0, 2500.0, 2000.0, 1500.0, 1000.0, 500.0, 0.0},
349 false, 50.0, {962.21, 1062.92, 873.019, 967.955, 799.857, 882.248, 731.282, 804.481, 664.708, 726.901,
350 599.229, 653.365, 535.172, 581.061, 472.101, 511.799, 411.877, 445.908, 353.651, 382.434,
351 299.225, 323.595, 247.998, 268.821, 200.983, 218.353, 158.261, 172.636, 119.932, 131.857,
352 86.3659, 95.7154, 58.1326, 65.4286, 35.2337, 40.7063, 17.7519, 21.5932, 5.95378, 8.21779});
356 runTest({10000.0, 11000.0, 12000.0, 13000.0, 14000.0, 15000.0, 16000.0, 17000.0, 18000.0, 19000.0,
357 20000.0, 21000.0, 22000.0, 23000.0, 24000.0, 25000.0, 26000.0, 27000.0, 28000.0, 29000.0},
358 true, 20.0, {0, 5.03316, 31.0906, 56.0286, 110.937, 128.441, 198.589, 210.596, 284.946, 284.878,
359 358.21, 345.452, 424.04, 395.573, 474.253, 435.555, 514.612, 461.857, 541.256, 478.229,
360 556.038, 480.233, 554.782, 468.493, 544.637, 447.635, 521.492, 415.265, 484.579, 367.228,
361 435.953, 311.242, 373.81, 241.924, 299.673, 162.093, 212.894, 75.2118, 112.83, 3.82094});
365 runTest({10000.0, 11000.0, 12000.0, 13000.0, 14000.0, 15000.0, 16000.0, 17000.0, 18000.0, 19000.0,
366 20000.0, 21000.0, 22000.0, 23000.0, 24000.0, 25000.0, 26000.0, 27000.0, 28000.0, 29000.0},
367 false, 20.0, {3404.82, 3509.87, 3338.75, 3472.73, 3312.48, 3447.74, 3285.74, 3426.31, 3249.38, 3383.13,
368 3192.44, 3322.71, 3119.21, 3241.8, 3022.51, 3142.98, 2908.89, 3022.1, 2772.3, 2881.64,
369 2617.82, 2722.29, 2440.46, 2542.63, 2246.61, 2345.11, 2033.39, 2129.17, 1798.72, 1892.51,
370 1544.68, 1634.35, 1273.08, 1361.87, 983.376, 1073.45, 673.695, 770.339, 345.319, 476.632});
374Real computeUnderlyingNpv(
const bool underlyingIsPayer,
const Real cap,
const Real floor,
const bool nakedOption) {
375 Date today(6, Jun, 2019);
376 Settings::instance().evaluationDate() = today;
378 auto dsc = Handle<YieldTermStructure>(QuantLib::ext::make_shared<FlatForward>(today, 0.01, ActualActual(ActualActual::ISDA)));
379 auto fwd = Handle<YieldTermStructure>(QuantLib::ext::make_shared<FlatForward>(today, 0.02, ActualActual(ActualActual::ISDA)));
381 Handle<DefaultProbabilityTermStructure>(QuantLib::ext::make_shared<FlatHazardRate>(today, 0.0050, ActualActual(ActualActual::ISDA)));
383 auto iborIndex = QuantLib::ext::make_shared<Euribor>(6 * Months, fwd);
387 Schedule schedule(today + 2 * Days, (today + 2 * Days) + 10 * Years, 6 * Months, NullCalendar(), Unadjusted,
388 Unadjusted, DateGeneration::Forward,
false);
389 IborLeg l(schedule, iborIndex);
390 l.withNotionals(10000.0);
392 if (cap != Null<Real>())
394 if (floor != Null<Real>())
399 leg = StrippedCappedFlooredCouponLeg(l);
403 auto rpa = QuantLib::ext::make_shared<RiskParticipationAgreement>(
404 std::vector<Leg>{leg}, std::vector<bool>{underlyingIsPayer}, std::vector<std::string>{
"EUR"},
405 std::vector<Leg>{},
false, std::vector<std::string>{}, 0.0, schedule.dates().front(), schedule.dates().back(),
411 QuantLib::ext::make_shared<LGM>(QuantLib::ext::make_shared<IrLgm1fConstantParametrization>(EURCurrency(), dsc, 0.0040, 0.01));
412 auto engine = QuantLib::ext::make_shared<NumericLgmRiskParticipationAgreementEngine>(
413 "EUR", std::map<std::string, Handle<YieldTermStructure>>{{
"EUR", dsc}}, std::map<std::string, Handle<Quote>>(),
414 lgm, 3.0, 10, 3.0, 10, def, Handle<Quote>());
418 rpa->setPricingEngine(engine);
419 return rpa->result<Real>(
"UnderlyingNpv");
425 constexpr Real tol = 1E-10;
430 Real plain = computeUnderlyingNpv(
false, Null<Real>(), Null<Real>(),
false);
433 Real capped = computeUnderlyingNpv(
false, 0.03, Null<Real>(),
false);
434 Real floored = computeUnderlyingNpv(
false, Null<Real>(), 0.01,
false);
435 Real collared = computeUnderlyingNpv(
false, 0.03, 0.01,
false);
438 Real cap = computeUnderlyingNpv(
false, 0.03, Null<Real>(),
true);
439 Real floor = computeUnderlyingNpv(
false, Null<Real>(), 0.01,
true);
440 Real collar = computeUnderlyingNpv(
false, 0.03, 0.01,
true);
442 BOOST_CHECK_CLOSE(capped + cap, plain, tol);
443 BOOST_CHECK_CLOSE(floored - floor, plain, tol);
444 BOOST_CHECK_CLOSE(collared - collar, plain, tol);
449 Real plain2 = computeUnderlyingNpv(
true, Null<Real>(), Null<Real>(),
false);
452 Real capped2 = computeUnderlyingNpv(
true, 0.03, Null<Real>(),
false);
453 Real floored2 = computeUnderlyingNpv(
true, Null<Real>(), 0.01,
false);
454 Real collared2 = computeUnderlyingNpv(
true, 0.03, 0.01,
false);
457 Real cap2 = computeUnderlyingNpv(
true, 0.03, Null<Real>(),
true);
458 Real floor2 = computeUnderlyingNpv(
true, Null<Real>(), 0.01,
true);
459 Real collar2 = computeUnderlyingNpv(
true, 0.03, 0.01,
true);
461 BOOST_CHECK_CLOSE(capped2 + cap2, plain2, tol);
462 BOOST_CHECK_CLOSE(floored2 - floor2, plain2, tol);
463 BOOST_CHECK_CLOSE(collared2 - collar2, plain2, tol);
466 BOOST_CHECK_CLOSE(plain, -plain2, tol);
467 BOOST_CHECK_CLOSE(capped, -capped2, tol);
468 BOOST_CHECK_CLOSE(floored, -floored2, tol);
469 BOOST_CHECK_CLOSE(collared, -collared2, tol);
470 BOOST_CHECK_CLOSE(cap, -cap2, tol);
471 BOOST_CHECK_CLOSE(floor, -floor2, tol);
472 BOOST_CHECK_CLOSE(collar, -collar2, tol);
475BOOST_AUTO_TEST_SUITE_END()
477BOOST_AUTO_TEST_SUITE_END()
QuantLib::BootstrapHelper< QuantLib::OptionletVolatilityStructure > helper
BOOST_AUTO_TEST_CASE(testStandardPayerSwap)